– Notes on https://www.udemy.com/course/salesforcedx
For my sfdx related aliases and functions see the sfdx.conf file in my linux repo.
# create sfdx directory in your home directory
cd sfdx
# get installer
wget https://developer.salesforce.com/media/salesforce-cli/sfdx-cli/channels/stable/sfdx-cli-linux-x64.tar.xz
# unpack file into sfdx directory
tar xJf sfdx-cli-linux-x64.tar.xz -C sfdx --strip-components 1
# run installer
./sfdx/install
The installer will istall the Salesforce CLI in /usr/local/bin/sfdx.
Update to newest version with sfdx update
.
script: sfdx/sfdx_scripts/sfdx_linux_installer automates this process on linux systems
– the open cli framework
CLI Runtime Configuration Values
sfdx force:config:set apiVersion=42.0 --global
will set the used api version to 42.
sfdx force:config:set apiVersion= --global
will set it back to current version.
sfdx force:config:list
will show a list of overridden configs. Default config doesn't show.
sfdx force:project:create -n Demo1
will create new project Demo1 as a sub-directory of the working directory.
Open project folder in VS Code by entering code Demo1/
in the terminal …
… or by pressing CTRL + o in VS Code and selecting Demo1 folder manually.
The sfdx-project.json was created with the global set api version. The login url can be edited here.
sfdx force:auth:web:login -a Demo1
will open production org web-login to authenticate the cli.
To authenticate a Sandbox or Custom Domain use sfdx force:auth:web:login -a Demo1 --instanceurl https://test.salesforce.com
If the authentication via web login doesn't work, try sfdx force:auth:device:login -a Demo1
sfdx force:auth:logout -u Demo1
will disconnect the prior authenticated Demo1 org from sfdx.
To open an authenticated org type sfdx force:org:open -u Demo1
or sfdx force:org:open -u 0221@myforce.net
Demo1 is the org alias, 0221@myforce.net is the user name – both work fine.
So it makes absolutely sense to use -a Demo1
option with :auth to give your orgs short and descriptive aliases.
List all your authenticated orgs with sfdx force:auth:list
=== authenticated orgs
ALIAS USERNAME ORG ID INSTANCE URL OAUTH METHOD
───── ──────────────── ────────────────── ─────────────────────────────────────────── ────────────
Demo1 0221@myforce.net 00D09000007FkECEA0 https://myforcenet-dev-ed.my.salesforce.com web
sfdx force:mdapi:retrieve -r ./mdapi -u 0221@myforce.net -p SFDX_Test
will receive SFDX_Test change set from org associated with user 0221@myforce.net.
./mdapi is the target directory for the extract. I've created it within the project directory.
A file unpackage.zip will be created. We can use unzip mdapi/unpackaged.zip
to extract all files.
Archive: mdapi/unpackaged.zip
inflating: SFDX_Test/objects/Test_Object__c.object
inflating: SFDX_Test/layouts/Test_Object__c-Test Object Layout.layout
inflating: SFDX_Test/package.xml
The directory SFDX_Test will contain all these extract elements.
sfdx force:mdapi:retrieve -r ./mdapi -u Demo1 -k mdapi/package.xml
if a package.xml exists.
-r ./mdapi = target location
-u Demo1 = org alias or username
-k mdapi/package.xml = package.xml location
This command will again result in an unpackaged.zip file in the targer directory.
Another way to retrieve metadata via package.xml is sfdx force:source:retrieve -u Demo1 -x ./package.xml
.
It is described in the Trailhead Package.xml Metadata Management module.
This method doesn't require to unzip the retrieved metadata, it will be placed in the force-app/main/default directory of the project.
metadata structure – everything is in the same place.
source format – own xml for each field, object, etc.
sfdx force:mdapi:convert -r mdapi -d force-app
to convert with metadata api.
I didn't manage to get this method to work with my sfdx version on linux
sfdx force:source:retrieve --manifest mdapi/package.xml -u Demo1
uses an existing package.xml (manifest) to retrieve the specified content directly in source format.
sfdx force:source:retrieve -m ApexClass -u Demo1
would retrieve all Apex classes from the Demo1 org.
The Metadata Coverage Report shows what data can be queried via the metadata api.
sfdx force:apex:class:create --classname MyApexClass --template DefaultApexClass --outputdir force-app/main/default/classes/
This command creates apex class MyApexClass in the specified directory.
The apex class can be edited with your editor of chice and deploeyed as following:
$ sfdx force:source:deploy --sourcepath force-app/main/default/classes/MyApexClass.cls -u Demo1
WARNING: apiVersion configuration overridden at "47.0"
Job ID | 0Ah7R9800NSjLHFGDA3
SOURCE PROGRESS | ████████████████████████████████████████ | 1/1 Components
=== Deployed Source
FULL NAME TYPE PROJECT PATH
─────────── ───────── ───────────────────────────────────────────────────────
MyApexClass ApexClass force-app/main/default/classes/MyApexClass.cls
MyApexClass ApexClass force-app/main/default/classes/MyApexClass.cls-meta.xml
sfdx force:source:retrieve --sourcepath force-app/main/default/classes -u Demo1
sourcepath can be used to specify a directory from the source org and retrieve all updates from there.
NOTE: This will only retrieve classes already existend in the local project. New classes won't be synced down automatically.
`sfdx force:source:retrieve --manifest mdapi/classes.xml -u Demo1 manifest to receive all or specific apex classes.
The following manifest will retrieve all clases due to the star wildcard:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Apex_Classes</fullName>
<description>Let's see if I can retrieve classes only.</description>
<types>
<members>*</members>
<name>ApexClass</name>
</types>
<version>50.0</version>
</Package>
To retrive only specific classes those individual members have to be specified:
<types>
<members>MyApexClass</members>
<members>MyApexClass2</members>
<name>ApexClass</name>
</types>
The manifest dosn't have to be named package.xml. I've named the above file classes.xml.
As it it is impossible to remember all terminal commands, most terminal applications come with am manual.
$ man sfdx
No manual entry for sfdx
sfdx apparently has no manual, but it makes very good use of the --help command.
$ sfdx --help
Salesforce CLI
VERSION
sfdx-cli/7.85.1-2fb9e41053 linux-x64 node-v12.18.3
USAGE
$ sfdx [COMMAND]
TOPICS
alias manage username aliases
auth authorize an org for use with the Salesforce CLI
config configure the Salesforce CLI
force tools for the Salesforce developer
plugins add/remove/create CLI plug-ins
schema List metadata types in your Salesforce org using the CLI
COMMANDS
autocomplete display autocomplete installation instructions
commands list all the commands
help display help for sfdx
plugins list installed plugins
update update the sfdx CLI
which show which plugin a command is in
To see the help page of source:retrieve and all its available parameters the command would be:
sfdx force:source:retrieve --help
there are also their short forms specified:
-p, --sourcepath=sourcepath
comma-separated list of source file paths to retrieve
-x, --manifest=manifest
file path for manifest (package.xml) of components to retrieve
The prior used --sourcepath is short -p, the --manifes is -x.
The short form of --help is -h.
sfdx force:apex:test:run -h
will provide all options for an apex test run.
Create a record sfdx force:data:record:create -h
sfdx force:data:record:create -s Account -u Demo1 -v "name='CFC – created from cli'"
will create an account with the name field filled. Enter multiple fields separated by space:
sfdx force:data:record:create -s Account -u Demo1 -v "name='CFC2' Industry='Energgy'"
The command creates an account named CFC2 and industry Energgy.
Update a record to correct that spelling mistake we can use the following command:
sfdx force:data:record:update -s Account -u Demo1 -v "Industry='Energy'" -i 0017R00002TF7zQQAT
Retrive information with get – in the case of the following command all fields and values from the CFC2 account:
sfdx force:data:record:get -s Account -u Demo1 -w "Name='CFC2'"
to receive the outcome in json format use:
sfdx force:data:record:get -s Account -u isv -w "Name='CFC2'" --json
Delete a record with command: sfdx force:data:record:delete -s Account -u Demo1 -w "Name='CFC2'"
Like the others delete would accept -i, --id or other options sfdx force:data:record:delete -h
for more.
soql in sfdx example: sfdx force:data:soql:query -u Demo1 -q "SELECT Id, Name, Email FROM User"
Export relational data: To receive relational data, like contacts of accounts use such an command:
sfdx force:data:tree:export -q "SELECT Id, Name, (SELECT FirstName, LastName FROM Contacts) FROM Account" -d /home/heiko/test -p -u Demo1
.
-d specifies the directory where the results should be saved (in json format).
-p generates mulitple sobject tree files and a plan definition file for aggregated import.
The output of this command looks like this:
Wrote 13 records to /home/heiko/test/Accounts.json
Wrote 20 records to /home/heiko/test/Contacts.json
Wrote 0 records to /home/heiko/test/Account-Contact-plan.json
Accounts.json (two example records):
{
"records": [
{
"attributes": {
"type": "Account",
"referenceId": "AccountRef1"
},
"Name": "Edge Communications"
},
{
"attributes": {
"type": "Account",
"referenceId": "AccountRef2"
},
"Name": "Burlington Textiles Corp of America"
}
]
}
Contacts.json (three example records from two accounts):
{
"records": [
{
"attributes": {
"type": "Contact",
"referenceId": "ContactRef1"
},
"FirstName": "Rose",
"LastName": "Gonzalez",
"AccountId": "@AccountRef1"
},
{
"attributes": {
"type": "Contact",
"referenceId": "ContactRef2"
},
"FirstName": "Sean",
{
"attributes": {
"type": "Contact",
"referenceId": "ContactRef3"
},
"FirstName": "Jack",
"LastName": "Rogers",
"AccountId": "@AccountRef2"
}
]
}
Account-Contact-plan.json (complete):
[
{
"sobject": "Account",
"saveRefs": true,
"resolveRefs": false,
"files": [
"Accounts.json"
]
},
{
"sobject": "Contact",
"saveRefs": false,
"resolveRefs": true,
"files": [
"Contacts.json"
]
}
]
The entry "referenceId": "AccountRef1" on the account object corresponds to the "AccountId": "@AccountRef1 entry on the contact.
This referential mapping together with Account-Contact-plan.json is required to import those records with their relations into an other org.
The Salesforce 18-digit id can't be used in this case as those ids would conflict with the target org.
To import those records into an other org use the plan file:
$ sfdx force:data:tree:import -p Account-Contact-plan.json -u Demo2
=== Import Results
Reference ID Type ID
──────────── ─────── ──────────────────
AccountRef1 Account 0017R00002TFgEgQAL
AccountRef2 Account 0017R00002TFgEhQAL
ContactRef1 Contact 0037R00002pcMTJQA2
ContactRef2 Contact 0037R00002pcMTKQA2
ContactRef3 Contact 0037R00002pcMTLQA2
Use simplified commands to export/import records individual without keeping their relations:
$ sfdx force:data:tree:export -q "SELECT Id, Name FROM Account" -u Demo1
$ sfdx force:data:tree:export -q "SELECT Id, LastName, FirstName FROM Contact" -u Demo1
# Then run the import command:
$ sfdx force:data:tree:import -f Contact.json,Account.json -u Demo2
sObject tree import requests can contain
- Up to a total of 200 records across all trees
- Up to five records of different types
- sObject trees up to five levels deep
Check out the Salesforce documentation for more information.
sfdx force:org:create -f config/project-scratch-def.json
executed in the main sfdx project folder will create a scratch org as defined in project-scratch-def.json.
If yo forget to set the alias with -a you can set it anytime later with sfdx alias:set scratch=test-wkuerukfcxub@example.com
.
You can display an ors limits (remaining, mx) with sfdx force:limits:api:display -u Demo1
.
$ sfdx force:limits:api:display -u Demo1
Name Remaining Max
─────────────────────────────────────────── ───────── ─────────
ActiveScratchOrgs 4 5
AnalyticsExternalDataSizeMB 40960 40960
BOZosCalloutHourlyLimit 20000 20000
ConcurrentAsyncGetReportInstances 200 200
ConcurrentEinsteinDataInsightsStoryCreation 5 5
sfdx force:data:soql:query -u prod -t -q "SELECT Id FROM ApexLog WHERE LogUser.Name = 'B2BMA Integration' AND Status = 'Success'" -r "csv" > out.csv
sfdx force:data:bulk:delete -u prod -s ApexLog -f ./out.csv