labunix's blog

labunixのラボUnix

sfdxのサポートが終了したのでsfコマンドについて調べてみる

■sfdxのサポートが終了したのでsfコマンドについて調べてみる

 https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_setup.meta/sfdx_setup/sfdx_setup_install_cli.htm

sfdx (v7) - 廃止
メモ
2023712 日をもって、sfdx (v7) の更新は終了しました。このような古いバージョンは、履歴管理の目的のためだけに保管されています。

■Salesforce CLI バージョン

$ sf --version
@salesforce/cli/2.30.8 linux-x64 node-v20.11.1

■インストール済みのコアプラグインとそのバージョン

$ sf plugins --core
@oclif/plugin-autocomplete 3.0.9 (core)
@oclif/plugin-commands 3.1.4 (core)
@oclif/plugin-help 6.0.13 (core)
@oclif/plugin-not-found 3.0.11 (core)
@oclif/plugin-plugins 4.2.5 (core)
@oclif/plugin-search 1.0.16 (core)
@oclif/plugin-update 4.1.13 (core)
@oclif/plugin-version 2.0.12 (core)
@oclif/plugin-warn-if-update-available 3.0.12 (core)
@oclif/plugin-which 3.1.0 (core)
@salesforce/cli 2.30.8 (core)
apex 3.0.25 (core)
auth 3.3.13 (core)
data 3.1.1 (core)
deploy-retrieve 3.2.16 (core)
info 3.0.27 (core)
limits 3.1.10 (core)
marketplace 1.0.25 (core)
org 3.3.14 (core)
packaging 2.1.10 (core)
schema 3.1.3 (core)
settings 2.0.27 (core)
sobject 1.1.13 (core)
source 3.1.15 (core)
telemetry 3.1.13 (core)
templates 56.0.16 (core)
trust 3.3.10 (core)
user 3.2.11 (core)

Uninstalled JIT Plugins:
community 3.0.21
custom-metadata 3.1.12
dev 2.1.13
devops-center 1.2.6
env 3.0.20
functions 1.22.11
signups 2.0.24
@salesforce/sfdx-plugin-lwc-test 1.1.1
@salesforce/sfdx-scanner 3.21.0

■使用可能なすべての Salesforce CLI コマンドの実行結果は固定長なので、サマリ説明は端折って表示

$ sf commands | awk '(NR>2){print substr($0,1,33)}' | column -c 140
 alias list                      	 force data bulk upsert          	 package version delete          
 alias set                       	 force lightning lwc test create 	 package version displayancestry 
 alias unset                     	 force lightning lwc test run    	 package version list            
 analytics generate template     	 force lightning lwc test setup  	 package version promote         
 apex generate class             	 generate function               	 package version report          
 apex generate trigger           	 help                            	 package version update          
 apex get log                    	 info releasenotes display       	 plugins                         
 apex get test                   	 lightning generate app          	 plugins add                     
 apex list log                   	 lightning generate component    	 plugins discover                
 apex run                        	 lightning generate event        	 plugins inspect                 
 apex run test                   	 lightning generate interface    	 plugins install                 
 apex tail log                   	 lightning generate test         	 plugins link                    
 autocomplete                    	 login functions                 	 plugins remove                  
 cmdt generate field             	 login functions jwt             	 plugins reset                   
 cmdt generate fromorg           	 logout functions                	 plugins trust verify            
 cmdt generate object            	 org assign permset              	 plugins uninstall               
 cmdt generate record            	 org assign permsetlicense       	 plugins unlink                  
 cmdt generate records           	 org create sandbox              	 plugins update                  
 commands                        	 org create scratch              	 project convert mdapi           
 community create                	 org create shape                	 project convert source          
 community list template         	 org create snapshot             	 project delete source           
 community publish               	 org create user                 	 project delete tracking         
 config get                      	 org delete sandbox              	 project deploy cancel           
 config list                     	 org delete scratch              	 project deploy pipeline quick   
 config set                      	 org delete shape                	 project deploy pipeline report  
 config unset                    	 org delete snapshot             	 project deploy pipeline resume  
 data create record              	 org disable tracking            	 project deploy pipeline start   
 data delete bulk                	 org display                     	 project deploy pipeline validate
 data delete record              	 org display user                	 project deploy preview          
 data delete resume              	 org enable tracking             	 project deploy quick            
 data export beta tree           	 org generate password           	 project deploy report           
 data export tree                	 org get snapshot                	 project deploy resume           
 data get record                 	 org list                        	 project deploy start            
 data import beta tree           	 org list auth                   	 project deploy validate         
 data import tree                	 org list limits                 	 project generate                
 data query                      	 org list metadata               	 project generate manifest       
 data query resume               	 org list metadata-types         	 project list ignored            
 data update record              	 org list shape                  	 project reset tracking          
 data upsert bulk                	 org list snapshot               	 project retrieve preview        
 data upsert resume              	 org list sobject record-counts  	 project retrieve start          
 deploy functions                	 org list users                  	 run function                    
 dev audit messages              	 org login access-token          	 run function start              
 dev convert messages            	 org login device                	 run function start container    
 dev convert script              	 org login jwt                   	 run function start local        
 dev generate command            	 org login sfdx-url              	 scanner rule add                
 dev generate flag               	 org login web                   	 scanner rule describe           
 dev generate library            	 org logout                      	 scanner rule list               
 dev generate plugin             	 org open                        	 scanner rule remove             
 doctor                          	 org resume sandbox              	 scanner run                     
 env compute collaborator add    	 org resume scratch              	 scanner run dfa                 
 env create compute              	 package1 version create         	 schema generate field           
 env delete                      	 package1 version create get     	 schema generate platformevent   
 env display                     	 package1 version display        	 schema generate sobject         
 env list                        	 package1 version list           	 schema generate tab             
 env log                         	 package create                  	 search                          
 env log tail                    	 package delete                  	 sobject describe                
 env logdrain add                	 package install                 	 sobject list                    
 env logdrain list               	 package install report          	 static-resource generate        
 env logdrain remove             	 package installed list          	 update                          
 env open                        	 package list                    	 version                         
 env var get                     	 package uninstall               	 visualforce generate component  
 env var list                    	 package uninstall report        	 visualforce generate page       
 env var set                     	 package update                  	 whatsnew                        
 env var unset                   	 package version create          	 which                           
 force data bulk delete          	 package version create list     	 whoami functions                
 force data bulk status          	 package version create report   

■サブコマンドで集計するとこんな感じ

$ sf commands | awk '(NR>2){print substr($0,1,33)}' | awk '{a[$1]+=1}END{for(n in a){print n,a[n] | "sort -V -k 1"}}' | column -c 140
alias 3			data 14			info 1			project 22		version 1
analytics 1		deploy 1		lightning 5		run 4			visualforce 2
apex 8			dev 7			login 2			scanner 6		whatsnew 1
autocomplete 1		doctor 1		logout 1		schema 4		which 1
cmdt 5			env 15			org 35			search 1		whoami 1
commands 1		force 6			package1 4		sobject 2
community 3		generate 1		package 18		static-resource 1
config 4		help 1			plugins 12		update 1

■orgやprojectが多いのは想像通り。login、logout、apex、sobject あたりをサブサブコマンドで集計
 サブコマンドのloginはfunctionsのためなので一旦スルー

$ sf commands | awk '(NR>2){print substr($0,1,33)}' | \
   awk '$1 ~ /org|project|login|logout|apex|sobject/{a[$1"_"$2]+=1}END{for(n in a){print n,a[n] | "sort -V -k 1"}}' | column -c 140
apex_generate 2		logout_functions 1	org_enable 1		org_open 1		project_list 1
apex_get 2		org_assign 2		org_generate 1		org_resume 2		project_reset 1
apex_list 1		org_create 5		org_get 1		project_convert 2	project_retrieve 2
apex_run 2		org_delete 4		org_list 9		project_delete 2	sobject_describe 1
apex_tail 1		org_disable 1		org_login 5		project_deploy 12	sobject_list 1
login_functions 2	org_display 2		org_logout 1		project_generate 2

■USAGE、TOPICS、COMMANDS とセクションが別れているので、とりあえずTOPICSセクションを抽出
 COMMANDSセクションも微妙、、、

$ sf org -h | lsec TOPICS
TOPICS
  org assign    Used to assign permissions to a user
  org create    Used to create a user
  org delete    Delete scratch orgs, sandboxes, org shapes, and org snapshots.
  org disable   Disable source tracking in an org.
  org display   Used to display a user
  org enable    Enable source tracking in an org.
  org generate  Generate commands for a user
  org get       Get details about a scratch org snapshot.
  org list      Used to list users
  org login     Authorize an org for use with Salesforce CLI.
  org resume    Resume an org creation that was started asynchronously, timed
                out, or was interrupted.

■「sf commands」で使いそうな org サブコマンドを抽出

$ sf commands | \
  awk '(NR>2 && $1 ~ /org/ && $2 ~ /list|log|open/ && $3 !~ /auth|shape|snapshot|access-token|device|jwt|sfdx-url/){print substr($0,1,140)}'
 org list                         List all orgs you’ve created or authenticated to.                                                       
 org list limits                  Display information about limits in your org.                                                             
 org list metadata                List the metadata components and properties of a specified type.                                          
 org list metadata-types          Display details about the metadata types that are enabled for your org.                                   
 org list sobject record-counts   Display record counts for the specified standard or custom objects.                                       
 org list users                   List all locally-authenticated users of an org.                                                           
 org login web                    Log in to a Salesforce org using the web server flow.                                                     
 org logout                       Log out of a Salesforce org.                                                                              
 org open                         Open your default scratch org, or another specified org, in a browser.  

■一旦 deploy しない方針で project サブコマンドを抽出

$ sf commands | awk '(NR>2 && $1 ~ /project/ && $2 !~ /convert|delete|deploy/ && $3 !~ /tracking/){print substr($0,1,140)}'
 project generate                 Generate a Salesforce DX project.                                                                         
 project generate manifest        Create a project manifest that lists the metadata components you want to deploy or retrieve.              
 project list ignored             Check your local project package directories for forceignored files.                                      
 project retrieve preview         Preview a retrieval to see what will be retrieved from the org, the potential conflicts, and the ignored f
 project retrieve start           Retrieve metadata from an org to your local project.                                    

■apex サブコマンドを抽出

$ sf commands | awk '(NR>2 && $1 ~ /apex/){print substr($0,1,140)}'
 apex generate class              Generate an Apex class.                                                                                   
 apex generate trigger            Generate an Apex trigger.                                                                                 
 apex get log                     Fetch the specified log or given number of most recent logs from the org.                                 
 apex get test                    Display test results for a specific asynchronous test run.                                                
 apex list log                    Display a list of IDs and general information about debug logs.                                           
 apex run                         Execute anonymous Apex code entered on the command line or from a local file.                             
 apex run test                    Invoke Apex tests in an org.                                                                              
 apex tail log                    Activate debug logging and display logs in the terminal.   

■sobject サブコマンドを抽出

$ sf commands | awk '(NR>2 && $1 ~ /sobject/){print substr($0,1,140)}'
 sobject describe                 Display the metadata for a standard or custom object or a Tooling API object.                             
 sobject list                     List all Salesforce objects of a specified category.              

■使いそうなコマンドがわかったら「-h」でヘルプを表示、他に使えるオプションを確認する

$ sf org login web -h
Log in to a Salesforce org using the web server flow.

USAGE
  $ sf org login web [--json] [-b chrome|edge|firefox] [-i <value>] [-r <value>] [-d] [-s] [-a <value>]

FLAGS
  -a, --alias=<value>         Alias for the org.
  -b, --browser=<option>      Browser in which to open the org.
                              <options: chrome|edge|firefox>
  -d, --set-default-dev-hub   Set the authenticated org as the default Dev Hub.
  -i, --client-id=<value>     OAuth client ID (also called consumer key) of your custom connected app.
  -r, --instance-url=<value>  URL of the instance that the org lives on.
  -s, --set-default           Set the authenticated org as the default that all org-related commands run against.

GLOBAL FLAGS
  --json  Format output as json.

■Developer Editionは本番組織の区分けなので

$ sf org login web -r https://login.salesforce.com/ -b chrome -a myDevEd
Successfully authorized labunix@XXXXX.dev with org ID 00DXXXXXXXXXXXXXXX

$ sf org list
   Type   Alias     Username                 Org ID             Status    Expires 
 ─ ────── ───────── ──────────────────────── ────────────────── ───────── ─────── 
   DevHub myDevEd   labunix@XXXXX.dev        00DXXXXXXXXXXXXXXX Connected         

Legend:  =Default DevHub, =Default Org      Use --all to see expired and deleted scratch orgs

■権限セット関連の sobject を抽出

$ sf sobject list -h
List all Salesforce objects of a specified category.

USAGE
  $ sf sobject list -o <value> [--json] [--api-version <value>] [-s <value>]

FLAGS
  -o, --target-org=<value>   (required) Username or alias of the target org. Not required if the `target-org` configuration variable is already
                             set.
  -s, --sobject=<value>      [default: ALL] Category of objects to list.
      --api-version=<value>  Override the api version used for api requests made by this command

GLOBAL FLAGS
  --json  Format output as json.

$ sf sobject list -o myDevEd | awk '/PermissionSet/'
MutingPermissionSet
PermissionSet
PermissionSetAssignment
PermissionSetEvent
PermissionSetEventStore
PermissionSetGroup
PermissionSetGroupComponent
PermissionSetLicense
PermissionSetLicenseAssign
PermissionSetTabSetting
PortalDelegablePermissionSet

■「権限セット割り当て」オブジェクトの項目について表示名を抽出

$ sf sobject describe -s PermissionSetAssignment -o myDevEd | jq -c .fields[].label
"PermissionSetAssignment ID"
"PermissionSet ID"
"PermissionSetGroup ID"
"Assignee ID"
"Date Assigned"
"Expires On"
"Is Active"
"Is Revoked"

■「権限セット割り当て」オブジェクトの項目について「"API参照名","表示名","リレーション名"」を抽出

$ sf sobject describe -s PermissionSetAssignment -o myDevEd | jq -c .fields[] | jq -c "[ .name, .label, .relationshipName ]"
["Id","PermissionSetAssignment ID",null]
["PermissionSetId","PermissionSet ID","PermissionSet"]
["PermissionSetGroupId","PermissionSetGroup ID","PermissionSetGroup"]
["AssigneeId","Assignee ID","Assignee"]
["SystemModstamp","Date Assigned",null]
["ExpirationDate","Expires On",null]
["IsActive","Is Active",null]
["IsRevoked","Is Revoked",null]

■カスタムオブジェクトは「__c」で探せるので、Trailheadで作った項目とそのリレーション先を知りたいときに使う

$ sf sobject list -o myDevEd | awk '/Zip_Code__c/'
Zip_Code__c

$ sf sobject describe -s Zip_Code__c -o myDevEd | jq -c .fields[] | jq -c "[ .name, .label, .relationshipName ]"
["Id","Record ID",null]
["OwnerId","Owner ID","Owner"]
["IsDeleted","Deleted",null]
["Name","Zip Code",null]
["CurrencyIsoCode","Currency ISO Code",null]
["CreatedDate","Created Date",null]
["CreatedById","Created By ID","CreatedBy"]
["LastModifiedDate","Last Modified Date",null]
["LastModifiedById","Last Modified By ID","LastModifiedBy"]
["SystemModstamp","System Modstamp",null]
["LastViewedDate","Last Viewed Date",null]
["LastReferencedDate","Last Referenced Date",null]
["State__c","State",null]
["City__c","City",null]

■オブジェクトマネージャにはなく、開発者コンソールでSOQLを発行できるオブジェクトに対して、
 「.label」や「.MasterLabel」、「.Name」出来る対象を簡単に見つけられるのが良い

$ sf sobject describe -s PermissionSetGroupComponent -o myDevEd | jq -c .fields[] | jq -c "[ .name, .label, .relationshipName ]"
["Id","PermissionSetGroupComponent ID",null]
["IsDeleted","Deleted",null]
["CreatedDate","Created Date",null]
["CreatedById","Created By ID","CreatedBy"]
["LastModifiedDate","Last Modified Date",null]
["LastModifiedById","Last Modified By ID","LastModifiedBy"]
["SystemModstamp","System Modstamp",null]
["PermissionSetGroupId","PermissionSetGroup ID","PermissionSetGroup"]
["PermissionSetId","PermissionSet ID or MutingPermissionSet ID","PermissionSet"]

■システム項目のById系(場合によってはOwner)は分かるけど、それ以外のリレーション名ってどのオブジェクト見ればいいの?とか
 ※OriginalOrderItem はエラーで拾えていない

$ sf sobject describe -s OrderItem -o myDevEd | jq -c .fields[] | jq -c "[ .name, .label, .relationshipName ]" | awk '!/null|ById/'
["Product2Id","Product ID","Product2"]
["OrderId","Order ID","Order"]
["PricebookEntryId","Price Book Entry ID","PricebookEntry"]
["OriginalOrderItemId","Original Order Item ID","OriginalOrderItem"]

$ sf sobject describe -s OrderItem -o myDevEd | jq -c .fields[] | jq -c "[ .name, .label, .relationshipName ]" | awk '!/null|ById/' \
  | awk -F\" '{print "sf sobject describe -s "$(NF-1)" -o myDevEd | jq -c .fields[] | jq -c \042[ .name, .label, .relationshipName ]\042"}' \
  | sh -x
+ sf sobject describe -s Product2 -o myDevEd
+ jq -c .fields[]
+ jq -c [ .name, .label, .relationshipName ]
["Id","Product ID",null]
["Name","Product Name",null]
["ProductCode","Product Code",null]
["Description","Product Description",null]
["IsActive","Active",null]
["CreatedDate","Created Date",null]
["CreatedById","Created By ID","CreatedBy"]
["LastModifiedDate","Last Modified Date",null]
["LastModifiedById","Last Modified By ID","LastModifiedBy"]
["SystemModstamp","System Modstamp",null]
["Family","Product Family",null]
["CurrencyIsoCode","Currency ISO Code",null]
["ExternalDataSourceId","External Data Source ID",null]
["ExternalId","External ID",null]
["DisplayUrl","Display URL",null]
["QuantityUnitOfMeasure","Quantity Unit Of Measure",null]
["IsDeleted","Deleted",null]
["IsArchived","Archived",null]
["LastViewedDate","Last Viewed Date",null]
["LastReferencedDate","Last Referenced Date",null]
["StockKeepingUnit","Product SKU",null]
["colorTheme__c","Color Theme",null]
["fragrance__c","Fragrance",null]
["glow__c","Glow",null]
["numberOfFlowers__c","Number of Flowers",null]
["percentOfOpening__c","Percent of Flower Opening",null]
+ sf sobject describe -s Order -o myDevEd
+ jq -c .fields[]
+ jq -c [ .name, .label, .relationshipName ]
["Id","Order ID",null]
["OwnerId","Owner ID","Owner"]
["ContractId","Contract ID","Contract"]
["AccountId","Account ID","Account"]
["Pricebook2Id","Price Book ID","Pricebook2"]
["OriginalOrderId","Order ID","OriginalOrder"]
["EffectiveDate","Order Start Date",null]
["EndDate","Order End Date",null]
["IsReductionOrder","Reduction Order",null]
["Status","Status",null]
["Description","Description",null]
["CustomerAuthorizedById","Customer Authorized By ID","CustomerAuthorizedBy"]
["CustomerAuthorizedDate","Customer Authorized Date",null]
["CompanyAuthorizedById","Company Authorized By ID","CompanyAuthorizedBy"]
["CompanyAuthorizedDate","Company Authorized Date",null]
["Type","Order Type",null]
["BillingStreet","Billing Street",null]
["BillingCity","Billing City",null]
["BillingState","Billing State/Province",null]
["BillingPostalCode","Billing Zip/Postal Code",null]
["BillingCountry","Billing Country",null]
["BillingLatitude","Billing Latitude",null]
["BillingLongitude","Billing Longitude",null]
["BillingGeocodeAccuracy","Billing Geocode Accuracy",null]
["BillingAddress","Billing Address",null]
["ShippingStreet","Shipping Street",null]
["ShippingCity","Shipping City",null]
["ShippingState","Shipping State/Province",null]
["ShippingPostalCode","Shipping Zip/Postal Code",null]
["ShippingCountry","Shipping Country",null]
["ShippingLatitude","Shipping Latitude",null]
["ShippingLongitude","Shipping Longitude",null]
["ShippingGeocodeAccuracy","Shipping Geocode Accuracy",null]
["ShippingAddress","Shipping Address",null]
["Name","Order Name",null]
["PoDate","PO Date",null]
["PoNumber","PO Number",null]
["OrderReferenceNumber","Order Reference Number",null]
["BillToContactId","Bill To Contact ID","BillToContact"]
["ShipToContactId","Ship To Contact ID","ShipToContact"]
["ActivatedDate","Activated Date",null]
["ActivatedById","Activated By ID","ActivatedBy"]
["StatusCode","Status Category",null]
["CurrencyIsoCode","Currency ISO Code",null]
["OrderNumber","Order Number",null]
["TotalAmount","Order Amount",null]
["CreatedDate","Created Date",null]
["CreatedById","Created By ID","CreatedBy"]
["LastModifiedDate","Last Modified Date",null]
["LastModifiedById","Last Modified By ID","LastModifiedBy"]
["IsDeleted","Deleted",null]
["SystemModstamp","System Modstamp",null]
["LastViewedDate","Last Viewed Date",null]
["LastReferencedDate","Last Referenced Date",null]
+ sf sobject describe -s PricebookEntry -o myDevEd
+ jq -c .fields[]
+ jq -c [ .name, .label, .relationshipName ]
["Id","Price Book Entry ID",null]
["Name","Product Name",null]
["Pricebook2Id","Price Book ID","Pricebook2"]
["Product2Id","Product ID","Product2"]
["CurrencyIsoCode","Currency ISO Code",null]
["UnitPrice","List Price",null]
["IsActive","Active",null]
["UseStandardPrice","Use Standard Price",null]
["CreatedDate","Created Date",null]
["CreatedById","Created By ID","CreatedBy"]
["LastModifiedDate","Last Modified Date",null]
["LastModifiedById","Last Modified By ID","LastModifiedBy"]
["SystemModstamp","System Modstamp",null]
["ProductCode","Product Code",null]
["IsDeleted","Deleted",null]
["IsArchived","Archived",null]
+ sf sobject describe -s OriginalOrderItem -o myDevEd
+ jq -c .fields[]
+ jq -c [ .name, .label, .relationshipName ]
Error (1): The requested resource does not exist

■apexサブコマンドはあくまで外側なので

$ sf apex tail log -o myDevEd
60.0 APEX_CODE,FINEST;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;NBA,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,FINER;WAVE,INFO;WORKFLOW,INFO
01:50:28.4 (4776689)|USER_INFO|[EXTERNAL]|005XXXXXXXXXXXX|labunix@XXXXXXXX.dev|(GMT+09:00) Japan Standard Time (Asia/Tokyo)|GMT+09:00

■apex*やflowはプロジェクト作って

$ sf sobject list -o myDevEd | awk '/Apex|Flow/' | column -c 140
ApexClass				BatchApexErrorEvent			FlowOrchestrationStageInstanceShare
ApexComponent				ConcurLongRunApexErrEvent		FlowOrchestrationStepInstance
ApexEmailNotification			FlowDefinitionView			FlowOrchestrationStepInstanceShare
ApexLog					FlowExecutionErrorEvent			FlowOrchestrationWorkItem
ApexPage				FlowInterview				FlowOrchestrationWorkItemShare
ApexPageInfo				FlowInterviewLog			FlowRecordRelation
ApexTestQueueItem			FlowInterviewLogEntry			FlowStageRelation
ApexTestResult				FlowInterviewLogShare			FlowTestResult
ApexTestResultLimits			FlowInterviewShare			FlowTestResultShare
ApexTestRunResult			FlowOrchestrationEvent			FlowTestView
ApexTestSuite				FlowOrchestrationInstance		FlowVariableView
ApexTrigger				FlowOrchestrationInstanceShare		FlowVersionView
ApexTypeImplementor			FlowOrchestrationLog			ProcessFlowMigration
AsyncApexJob				FlowOrchestrationStageInstance

■Apexやフローはリレーションとか考えなくても一覧はSOQLで取れる
 AsyncApexJob はちょっと別物だけど、、、

$ echo "ApexClass ApexComponent ApexPage ApexTrigger AsyncApexJob ApexTestSuite" | \
  awk '{for(sobject=1;sobject<=NF;sobject++){print "echo ---["$sobject"];sf sobject describe -s "$sobject" -o myDevEd | jq -c .fields[] | jq -c \042[ .name, .label, .type, .relationshipName ]\42 | sort -V"}}' | sh
---[ApexClass]
["ApiVersion","Api Version","double",null]
["BodyCrc","Body CRC","double",null]
["Body","Body","textarea",null]
["CreatedById","Created By ID","reference","CreatedBy"]
["CreatedDate","Created Date","datetime",null]
["Id","Class ID","id",null]
["IsValid","Is Valid","boolean",null]
["LastModifiedById","Last Modified By ID","reference","LastModifiedBy"]
["LastModifiedDate","Last Modified Date","datetime",null]
["LengthWithoutComments","Size Without Comments","int",null]
["NamespacePrefix","Namespace Prefix","string",null]
["Name","Name","string",null]
["Status","Status","picklist",null]
["SystemModstamp","System Modstamp","datetime",null]
---[ApexComponent]
["ApiVersion","Api Version","double",null]
["ControllerKey","Controller Key","string",null]
["ControllerType","Controller Type","picklist",null]
["CreatedById","Created By ID","reference","CreatedBy"]
["CreatedDate","Created Date","datetime",null]
["Description","Description","textarea",null]
["Id","Component ID","id",null]
["LastModifiedById","Last Modified By ID","reference","LastModifiedBy"]
["LastModifiedDate","Last Modified Date","datetime",null]
["Markup","Markup","textarea",null]
["MasterLabel","Label","string",null]
["NamespacePrefix","Namespace Prefix","string",null]
["Name","Name","string",null]
["SystemModstamp","System Modstamp","datetime",null]
---[ApexPage]
["ApiVersion","Api Version","double",null]
["ControllerKey","Controller Key","string",null]
["ControllerType","Controller Type","picklist",null]
["CreatedById","Created By ID","reference","CreatedBy"]
["CreatedDate","Created Date","datetime",null]
["Description","Description","textarea",null]
["Id","Page ID","id",null]
["IsAvailableInTouch","Available for Lightning Experience, Experience Builder sites, and the mobile app","boolean",null]
["IsConfirmationTokenRequired","Require CSRF protection on GET requests","boolean",null]
["LastModifiedById","Last Modified By ID","reference","LastModifiedBy"]
["LastModifiedDate","Last Modified Date","datetime",null]
["Markup","Markup","textarea",null]
["MasterLabel","Label","string",null]
["NamespacePrefix","Namespace Prefix","string",null]
["Name","Name","string",null]
["SystemModstamp","System Modstamp","datetime",null]
---[ApexTrigger]
["ApiVersion","Api Version","double",null]
["BodyCrc","Body CRC","double",null]
["Body","Body","textarea",null]
["CreatedById","Created By ID","reference","CreatedBy"]
["CreatedDate","Created Date","datetime",null]
["Id","Trigger ID","id",null]
["IsValid","Is Valid","boolean",null]
["LastModifiedById","Last Modified By ID","reference","LastModifiedBy"]
["LastModifiedDate","Last Modified Date","datetime",null]
["LengthWithoutComments","Size Without Comments","int",null]
["NamespacePrefix","Namespace Prefix","string",null]
["Name","Name","string",null]
["Status","Status","picklist",null]
["SystemModstamp","System Modstamp","datetime",null]
["TableEnumOrId","Custom Object Definition ID","picklist",null]
["UsageAfterDelete","AfterDelete","boolean",null]
["UsageAfterInsert","AfterInsert","boolean",null]
["UsageAfterUndelete","AfterUndelete","boolean",null]
["UsageAfterUpdate","AfterUpdate","boolean",null]
["UsageBeforeDelete","BeforeDelete","boolean",null]
["UsageBeforeInsert","BeforeInsert","boolean",null]
["UsageBeforeUpdate","BeforeUpdate","boolean",null]
["UsageIsBulk","IsBulk","boolean",null]
---[AsyncApexJob]
["ApexClassId","Class ID","reference","ApexClass"]
["CompletedDate","Completion Date","datetime",null]
["CreatedById","Created By ID","reference","CreatedBy"]
["CreatedDate","Created Date","datetime",null]
["CronTriggerId","Scheduled Job ID","reference","CronTrigger"]
["ExtendedStatus","Status Detail","string",null]
["Id","Apex Job ID","id",null]
["JobItemsProcessed","Batches Processed","int",null]
["JobType","Job Type","picklist",null]
["LastProcessedOffset","Offset of last ID processed and committed","int",null]
["LastProcessed","Last ID processed and committed","string",null]
["MethodName","Apex Method","string",null]
["NumberOfErrors","Failures","int",null]
["ParentJobId","Apex Job ID","reference",null]
["Status","Status","picklist",null]
["TotalJobItems","Total Batches","int",null]
---[ApexTestSuite]
["CreatedById","Created By ID","reference","CreatedBy"]
["CreatedDate","Created Date","datetime",null]
["Id","Test Suite ID","id",null]
["IsDeleted","Deleted","boolean",null]
["LastModifiedById","Last Modified By ID","reference","LastModifiedBy"]
["LastModifiedDate","Last Modified Date","datetime",null]
["SystemModstamp","System Modstamp","datetime",null]
["TestSuiteName","Test Suite Name","string",null]

$ sf sobject describe -s FlowDefinitionView -o myDevEd | jq -c .fields[] | jq -c "[ .name, .label, .type ]"
["Id","Flow Definition View ID","id"]
["DurableId","Durable ID","string"]
["ApiName","Flow API Name","string"]
["Label","Flow Label","string"]
["Description","Flow Description","string"]
["ProcessType","Process Type","picklist"]
["TriggerType","Trigger","picklist"]
["NamespacePrefix","Flow Namespace","string"]
["ActiveVersionId","Active Flow Version API Name or ID","string"]
["LatestVersionId","Latest Flow Version API Name or ID","string"]
["LastModifiedBy","Last Modified By","string"]
["IsActive","Active","boolean"]
["IsOutOfDate","Is Using an Older Version","boolean"]
["LastModifiedDate","Last Modified Date","datetime"]
["IsTemplate","Template","boolean"]
["IsOverridable","Overridable","boolean"]
["OverriddenById","Flow Definition View ID","string"]
["SourceTemplateId","Flow Definition View ID","string"]
["OverriddenFlowId","Flow Definition View ID","string"]
["IsSwingFlow","Is Swing Flow","boolean"]
["Builder","Built with","string"]
["ManageableState","Package State","picklist"]
["InstalledPackageName","Package Name","string"]
["TriggerObjectOrEventLabel","Triggering Object or Platform Event Label","string"]
["TriggerObjectOrEventId","Entity Definition ID","string"]
["RecordTriggerType","Record Trigger Type","picklist"]
["HasAsyncAfterCommitPath","Has Asynchronous After Commit Path","boolean"]
["VersionNumber","Version Number","int"]
["TriggerOrder","Trigger Order","int"]
["Environments","Environments","multipicklist"]
["ApiVersion","Api Version","int"]

■Apexやフローの中身を持ってくるにはprojectを作る必要がある

$ sf project generate -h
Generate a Salesforce DX project.

USAGE
  $ sf project generate -n <value> [--json] [-t standard|empty|analytics] [-d <value>] [-s <value>] [-p <value>]
    [-x] [--api-version <value>]

FLAGS
  -d, --output-dir=<value>           [default: .] Directory for saving the created files.
  -n, --name=<value>                 (required) Name of the generated project.
  -p, --default-package-dir=<value>  [default: force-app] Default package directory name.
  -s, --namespace=<value>            Namespace associated with this project and any connected scratch orgs.
  -t, --template=<option>            [default: standard] Template to use for project creation.
                                     <options: standard|empty|analytics>
  -x, --manifest                     Generate a manifest (package.xml) for change-set based development.
      --api-version=<value>          Will set this version as sourceApiVersion in the sfdx-project.json file

GLOBAL FLAGS
  --json  Format output as json.

COMMANDS
  project generate manifest  Create a project manifest that lists the metadata components you want to deploy or retrieve.


■myworkという名前のプロジェクトを作る
 ※パッケージディレクトリ名はデフォルトの「force-app」のままで良い
 ※「package.xml」は無いとゼロから自分で作るはめになるので、繰り返し取得する必要があればオプションを付けましょう

$ sf project generate --name myDevEd --manifest
target dir = /home/labunix
   create myDevEd/config/project-scratch-def.json
   create myDevEd/README.md
   create myDevEd/sfdx-project.json
   create myDevEd/manifest/package.xml
   create myDevEd/.husky/pre-commit
   create myDevEd/.vscode/extensions.json
   create myDevEd/.vscode/launch.json
   create myDevEd/.vscode/settings.json
   create myDevEd/force-app/main/default/lwc/.eslintrc.json
   create myDevEd/force-app/main/default/aura/.eslintrc.json
   create myDevEd/scripts/soql/account.soql
   create myDevEd/scripts/apex/hello.apex
   create myDevEd/.forceignore
   create myDevEd/.gitignore
   create myDevEd/.prettierignore
   create myDevEd/.prettierrc
   create myDevEd/jest.config.js
   create myDevEd/package.json

■FlowDefinitionViewが無いが一旦スルーする
 AsyncApexJob はApexClassをリレーションに持つ特殊なオブジェクトなので除外
 AuraDefinitionBundle、LightningComponentBundle、StaticResourceは今は関係無いので除外

$ awk -F'[<>]' '/name/{print $3}' myDevEd/manifest/package.xml
ApexClass
ApexComponent
ApexPage
ApexTestSuite
ApexTrigger
AuraDefinitionBundle
LightningComponentBundle
StaticResource

■「package.xml」を指定してメタデータを取得

$ sf project retrieve start -h
Retrieve metadata from an org to your local project.

USAGE
  $ sf project retrieve start -o <value> [--json] [-a <value>] [-c] [-x <value> | -m <value> | -d <value>] [-r <value> |
    -n <value> | ] [--single-package -t <value>] [-w <value>] [-z ] [--zip-file-name <value> ]

FLAGS
  -a, --api-version=<value>      Target API version for the retrieve.
  -c, --ignore-conflicts         Ignore conflicts and retrieve and save files to your local filesystem, even if they overwrite your local changes.
  -d, --source-dir=<value>...    File paths for source to retrieve from the org.
  -m, --metadata=<value>...      Metadata component names to retrieve. Wildcards ( `*` ) supported as long as you use quotes, such as
                                 `ApexClass:MyClass*`
  -n, --package-name=<value>...  Package names to retrieve.
  -o, --target-org=<value>       (required) Login username or alias for the target org.
  -r, --output-dir=<value>       Directory root for the retrieved source files.
  -w, --wait=<value>             [default: 33 minutes] Number of minutes to wait for the command to complete and display results to the terminal
                                 window.
  -x, --manifest=<value>         File path for the manifest (package.xml) that specifies the components to retrieve.

METADATA API FORMAT FLAGS
  -t, --target-metadata-dir=<value>  Directory that will contain the retrieved metadata format files or ZIP.
  -z, --unzip                        Extract all files from the retrieved zip file.
      --single-package               Indicates that the zip file points to a directory structure for a single package.
      --zip-file-name=<value>        File name to use for the retrieved zip file.

GLOBAL FLAGS
  --json  Format output as json.

■メタデータを指定してzip形式で取得

$ cd myDevEd/;sf project retrieve start --metadata ApexClass ApexComponent ApexPage ApexTestSuite ApexTrigger -o myDevEd --target-metadata-dir output ;cd ..
Retrieving v59.0 metadata from labunix@XXXXX.dev using the v60.0 SOAP API
Preparing retrieve request... Succeeded
Wrote retrieve zip file to /home/labunix/myDevEd/output/unpackaged.zip.

$ zipinfo myDevEd/output/unpackaged.zip | \
  awk '/unpackaged/&&!/package.xml|Archive:/{gsub("unpackaged/|\..*","",$NF);print $NF | "sort -uV"}' | \
  awk -F\/ '{a[$1]+=1}END{for(n in a){print n,a[n] | "sort -k 1 -V"}}'
classes 75
components 5
pages 47
triggers 8

■フローを取得
 ※FlowDefinitionViewはFlowで取れる。WorkFlowも併せて取っておく
 ※もう新規では作れないはずのBuilderはFlowに分類される

$ cd myDevEd/;sf project retrieve start --metadata Flow -o myDevEd --target-metadata-dir output2 ;cd ..
Retrieving v59.0 metadata from labunix@XXXXX.dev using the v60.0 SOAP API
Preparing retrieve request... Succeeded
Wrote retrieve zip file to /home/labunix/myDevEd/output2/unpackaged.zip.

$ cd myDevEd/;sf project retrieve start --metadata WorkFlow -o myDevEd --target-metadata-dir output3 ;cd ..
Retrieving v59.0 metadata from labunix@XXXXX.dev using the v60.0 SOAP API
Preparing retrieve request... Succeeded
Wrote retrieve zip file to /home/labunix/myDevEd/output3/unpackaged.zip.

$ zipinfo myDevEd/output2/unpackaged.zip | \
  awk '/unpackaged/&&!/package.xml|Archive:/{gsub("unpackaged/|\..*","",$NF);print $NF | "sort -uV"}' | \
  awk -F\/ '{a[$1]+=1}END{for(n in a){print n,a[n] | "sort -k 1 -V"}}'
flows 25

$ zipinfo myDevEd/output3/unpackaged.zip | \
  awk '/unpackaged/&&!/package.xml|Archive:/{gsub("unpackaged/|\..*","",$NF);print $NF | "sort -uV"}' | \
  awk -F\/ '{a[$1]+=1}END{for(n in a){print n,a[n] | "sort -k 1 -V"}}'
workflows 4