Skip to content

exiahuang/sfdc-cli

Repository files navigation

sfdc-cli

exiahuang/sfdc-cli is a sfdc development kit. It is licensed under the Apache License 2.0

feature

install

install from pip

pip3 install sfdc-cli

install from git

git clone https://github.com/exiahuang/sfdc-cli
python3 setup.py install

Summary

command description
sfdc project:init init sfdc project
sfdc meta:retrieve retrieve metadata
sfdc meta:template:apex:create init apex from tempalte
sfdc meta:template:trigger:create init trigger from tempalte
sfdc meta:template:page:create init page(visualforce) from tempalte
sfdc meta:template:component:create init component(visualforce) from tempalte
sfdc meta:new create metadata in sfdc server
sfdc meta:update update metadata in sfdc server
sfdc meta:update:force force update metadata in sfdc server
sfdc meta:delete delete metadata in sfdc server
sfdc meta:refresh refresh metadata in sfdc server
sfdc meta:attr print metadata attribute
sfdc meta:refresh:dir refresh metadata dir from sfdc server
sfdc packagexml:server build all packagexml from server
sfdc packagexml:local scan local directory to build package.xml
sfdc apex:execute Executes anonymous Apex code
sfdc apex:test:run run apex testclass
sfdc apex:test:coverage get apex coverage
sfdc sobject:list list sobject
sfdc sobject:fields:desc describe sobject fields
sfdc sobject:export:xlsx export sfdc sobject as excel file
sfdc sobject:data:create insert sobject data from json data
sfdc sobject:data:update update sobject data from json data
sfdc sobject:data:get get sobject data from sfdc server
sfdc sobject:data:delete delete sobject data from sfdc server
sfdc data:soql:query soql query
sfdc data:tooling:query tooling query
sfdc call:rest:api call salesforce rest api
sfdc coder:snippet:soql soql snippet creator
sfdc coder:apex:snippet:insert:data:from:soql create apex code from soql query
sfdc coder:apex:snippet:insert:ramdam:data create insert sobject code, ramdam data
sfdc coder:apex:testclass:generator generator testclass from apex code
sfdc coder:apex:page:generator generator VisualForce/Controller/DTO/DAO Code from sobject
sfdc coder:copy:aura copy lightning
sfdc coder:permission:build create permission metadata
sfdc folder:list list folder
sfdc download:attachment download salesforce attachment
sfdc ant:migration:tool init Ant Migration Tool

Usage

print help

sfdc -h
usage: sfdc [-h]

sfdc development kit v0.1.0

positional arguments:

    ant:migration:tool  see `ant:migration:tool -h`
    apex:execute        see `apex:execute -h`
    apex:test:coverage  see `apex:test:coverage -h`
    apex:test:run       see `apex:test:run -h`
    call:rest:api       see `call:rest:api -h`
    coder:apex:page:generator
                        see `coder:apex:page:generator -h`
    coder:apex:snippet:insert:data:from:soql
                        see `coder:apex:snippet:insert:data:from:soql -h`
    coder:apex:snippet:insert:ramdam:data
                        see `coder:apex:snippet:insert:ramdam:data -h`
    coder:apex:testclass:generator
                        see `coder:apex:testclass:generator -h`
    coder:copy:aura     see `coder:copy:aura -h`
    coder:permission:build
                        see `coder:permission:build -h`
    coder:permission:list
                        see `coder:permission:list -h`
    coder:snippet:soql  see `coder:snippet:soql -h`
    data:soql:query     see `data:soql:query -h`
    data:tooling:query  see `data:tooling:query -h`
    download:attachment
                        see `download:attachment -h`
    folder:list         see `folder:list -h`
    meta:attr           see `meta:attr -h`
    meta:cache          see `meta:cache -h`
    meta:delete         see `meta:delete -h`
    meta:new            see `meta:new -h`
    meta:refresh        see `meta:refresh -h`
    meta:refresh:aura   see `meta:refresh:aura -h`
    meta:refresh:dir    see `meta:refresh:dir -h`
    meta:retrieve       see `meta:retrieve -h`
    meta:template:apex  see `meta:template:apex -h`
    meta:template:component
                        see `meta:template:component -h`
    meta:template:page  see `meta:template:page -h`
    meta:template:trigger
                        see `meta:template:trigger -h`
    meta:update         see `meta:update -h`
    packagexml:local    see `packagexml:local -h`
    packagexml:server   see `packagexml:server -h`
    project:init        see `project:init -h`
    sobject:data:create
                        see `sobject:data:create -h`
    sobject:data:delete
                        see `sobject:data:delete -h`
    sobject:data:get    see `sobject:data:get -h`
    sobject:data:update
                        see `sobject:data:update -h`
    sobject:export:xlsx
                        see `sobject:export:xlsx -h`
    sobject:fields:desc
                        see `sobject:fields:desc -h`
    sobject:list        see `sobject:list -h`
    tools:json:format   json format
    help                see `help -h`

optional arguments:
  -h, --help            show this help message and exit

new project

# for product
sfdc project:init -d project/sfdc-project1 -u username -p password -t security_token -s src -v api_version
# for sandbox/stgfull
sfdc project:init -d project/sfdc-project1 -u username -p password -t security_token -s src -v api_version --sandbox

cd project/sfdc-project1

metadata retrieve

# retrieve zip file of all metadata
sfdc meta:retrieve -p . -d package_dir -n package.zip

# retrieve zip file of choice metadata : ApexClass ApexTrigger ApexPage
sfdc meta:retrieve -p . -d package_dir -n package1.zip -m ApexClass ApexTrigger ApexPage ApexComponent CustomObject

# retrieve metadata and unzip, source path: src
sfdc meta:retrieve -p . -d package_dir -n package2.zip -m ApexClass ApexTrigger ApexPage AuraDefinitionBundle LightningComponentBundle --unzip --delete_after_unzip


sfdc meta:retrieve -p . -d package_dir -n package2.zip -m CustomObject --unzip --delete_after_unzip

sfdc meta:retrieve -p . -d package_dir -n package2.zip -m PermissionSet --unzip --delete_after_unzip

metadata template

init apex class from template

sfdc meta:template:apex -n HelloApex --template ApexClass.cls
sfdc meta:template:apex -n HelloApexBatch --template BatchApexClass.cls
sfdc meta:template:apex -n HelloApexTest --template UnitTestApexClass.cls
sfdc meta:template:apex -n HelloApexBatchTest --template BDDUnitTestApexClass.cls

init trigger from template

sfdc meta:template:trigger -n HelloApexTrigger --sobject Opportunity --template ApexTrigger.trigger
sfdc meta:template:trigger -n HelloApexTriggerAllEvents --sobject Opportunity --template ApexTriggerAllEvents.trigger
sfdc meta:template:trigger -n HelloApexTriggerBulk --sobject Opportunity --template ApexTriggerBulk.trigger

init visualforce from template

sfdc meta:template:page -n HelloApexPage --template ApexPage.page
sfdc meta:template:page -n HelloHeaderPageBlock --template HeaderPageBlock.page

init visualforce component

sfdc meta:template:component -n HelloCmp

metadata new/update/refresh/delete

new metadata

sfdc meta:new -p . -s ./src/classes/HelloApex.cls
sfdc meta:new -p . -s ./src/classes/HelloApexBatch.cls
sfdc meta:new -p . -s ./src/classes/HelloApexTest.cls
sfdc meta:new -p . -s ./src/classes/HelloApexBatchTest.cls
sfdc meta:new -p . -s ./src/pages/HelloApexPage.page
sfdc meta:new -p . -s ./src/components/HelloCmp.component
sfdc meta:new -p . -s ./src/triggers/HelloApexTrigger.trigger --sobject Opportunity
sfdc meta:new -p . -s ./src/triggers/HelloApexTriggerAllEvents.trigger --sobject Opportunity
sfdc meta:new -p . -s ./src/triggers/HelloApexTriggerBulk.trigger --sobject Opportunity

update metadata

sfdc meta:update -p . -s ./src/classes/HelloApex.cls
sfdc meta:update -p . -s ./src/classes/HelloApexBatch.cls
sfdc meta:update -p . -s ./src/classes/HelloApexTest.cls
sfdc meta:update -p . -s ./src/classes/HelloApexBatchTest.cls
sfdc meta:update -p . -s ./src/pages/HelloApexPage.page
sfdc meta:update -p . -s ./src/components/HelloCmp.component
sfdc meta:update -p . -s ./src/triggers/HelloApexTrigger.trigger
sfdc meta:update -p . -s ./src/triggers/HelloApexTriggerAllEvents.trigger
sfdc meta:update -p . -s ./src/triggers/HelloApexTriggerBulk.trigger

metadata refresh

metadata refresh by filepath

# refresh apex/trigger/page/copmonent/ aura file
sfdc meta:refresh -p . -s src/classes/HelloApex.cls
sfdc meta:refresh -p . -s ./src/classes/HelloApex.cls
sfdc meta:refresh -p . -s ./src/classes/HelloApexBatch.cls
sfdc meta:refresh -p . -s ./src/aura/HelloWorld/HelloWorld.cmp
sfdc meta:refresh -p . -s ./src/aura/HelloWorld/HelloWorld.css
sfdc meta:refresh -p . -s ./src/aura/HelloWorld

metadata refresh by directory

support directorys, read more

# refresh directory, examples
sfdc meta:refresh:dir -p . -d ./src/classes
sfdc meta:refresh:dir -p . -d ./src/triggers
sfdc meta:refresh:dir -p . -d ./src/components
sfdc meta:refresh:dir -p . -d ./src/pages
sfdc meta:refresh:dir -p . -d ./src/layouts
sfdc meta:refresh:dir -p . -d ./src/lwc
sfdc meta:refresh:dir -p . -d ./src/aura

# refresh one aura componet
sfdc meta:refresh:aura -p . -s ./src/aura/HelloWorld

delete metadata

sfdc meta:delete -p . -s ./src/classes/HelloApex.cls
sfdc meta:delete -p . -s ./src/classes/HelloApexBatch.cls
sfdc meta:delete -p . -s ./src/classes/HelloApexTest.cls
sfdc meta:delete -p . -s ./src/classes/HelloApexBatchTest.cls
sfdc meta:delete -p . -s ./src/pages/HelloApexPage.page
sfdc meta:delete -p . -s ./src/components/HelloCmp.component
sfdc meta:delete -p . -s ./src/triggers/HelloApexTrigger.trigger

metadata attribute

sfdc meta:attr -p . -s ./src/classes/HelloApex.cls

package.xml

build from server

# build package in current directory, filename package.xml
sfdc packagexml:server

sfdc packagexml:server -p . -d . -n package.xml

build from local

scan directory and build package.xml

sfdc packagexml:local --scandir ./src --savedir . -n package.xml

sfdc apex

Executes anonymous Apex code

# create a apex code
mkdir ./tmp/
echo "System.debug('hello world');" > ./tmp/HelloApex.apex

# run the apex code
sfdc apex:execute -p . -s ./tmp/HelloApex.apex

# use pipe
cat ./tmp/HelloApex.apex | sfdc apex:execute -p .

run apex testclass

sfdc apex:test:run -p . -s ./src/classes/HelloApexTest.cls
sfdc apex:test:run -p . -s ./src/classes/HelloApexBatchTest.cls

get coverage

sfdc apex:test:coverage -p . -f ./log/apex_coverage.log

sobject

create sobject data

# insert a account
echo "{\"Name\":\"exiahuang\"}" | sfdc sobject:data:create -s Account

# use json_data_file to create sobject data
sfdc sobject:data:create -s Account --data $json_data_file_path

get sobject data

sfdc sobject:data:get -s Account --id $account_id

delete sobject data

sfdc sobject:data:delete -s Account --id $account_id

update sobject data

# update sobject data from pipe
echo "{\"Phone\":\"080-0000-0000\"}" | sfdc sobject:data:update -s Account --id $account_id

# update sobject data from json file
sfdc sobject:data:update -s Account --id $account_id --data $json_data_file_path

list sobject

cd $project_dir
# print in console
sfdc sobject:list

# save as markdown file
sfdc sobject:list > log/sobject.md

export sobject as xlsx file

cd $project_dir
sfdc sobject:export:xlsx -s log/sobject.xlsx

describe fields

sfdc sobject:fields:desc -s $sobject_name

data query

soql query

sfdc data:soql:query -s "SELECT id,name from USER limit 10"

tooling query

sfdc data:tooling:query -s "SELECT Id,Name FROM ApexClass limit 100"

call salesforce rest api

Get method

# call /services/data/v45.0/sobjects
sfdc call:rest:api -e /services/data/v45.0/sobjects

# call /services/data/v45.0/sobjects/Account
sfdc call:rest:api -e /services/data/v45.0/sobjects/Account
sfdc call:rest:api -e /services/data/v45.0/sobjects/Opportunity

use file as params

echo '{"q": "Select Id, Name From ApexClass Limit 3"}' > tmp/sf_rest_test.json
sfdc call:rest:api -m GET -e /services/data/v45.0/tooling/query --use_params --params tmp/sf_rest_test.json

use pipe to call rest api

example : query ApexCodeCoverage

# example1 : query ApexCodeCoverage
echo '{"q": "SELECT Id, ApexTestClassId, TestMethodName, ApexClassorTriggerId, NumLinesCovered, NumLinesUncovered, Coverage FROM ApexCodeCoverage"}' | sfdc call:rest:api -m GET -e /services/data/v45.0/tooling/query --use_params


# example1 : query ApexClass
echo '{"q": "Select Id, Name From ApexClass Limit 3"}' | sfdc call:rest:api -m GET -e /services/data/v45.0/tooling/query --use_params

code creator

create soql

#
sfdc coder:snippet:soql -s $sobject_name --custom_field_only --updateable_field_only --include_comment --include_relationship

#
sfdc coder:snippet:soql -s Account  --custom_field_only --updateable_field_only --include_comment --include_relationship

insert sobject data code snippet from soql

sfdc coder:apex:snippet:insert:data:from:soql -s $soql
sfdc coder:apex:snippet:insert:data:from:soql -s "SELECT name, firstname, lastname FROM Account LIMIT 2"

insert sobject data code snippet

sfdc coder:apex:snippet:insert:ramdam:data -s $sobject_name --all_fields
sfdc coder:apex:snippet:insert:ramdam:data -s Account --all_fields

generator testclass from apex

sfdc coder:apex:testclass:generator -f $apex_code_file_path

generator VisualForce/Controller/DTO/DAO Code from sobject

sfdc coder:apex:page:generator --sobject $sobject_name --savedir tmp/mycode/src --custom_field_only --include_validate

copy lightning

sfdc coder:copy:aura -f $from_lightning_path -t $to_lightning_path
sfdc coder:copy:aura -f /app/project/sfdc-project1/src/aura/HelloWorld -t /app/project/sfdc-project1/src/aura/HelloWorld1

create permission metadata

retrieve sobject metadata first

# retrieve sobject metadata
sfdc meta:retrieve -p . -d package_dir -n package2.zip -m CustomObject --unzip --delete_after_unzip
# or use meta:refresh:dir
sfdc meta:refresh:dir -p . -d ./src/objects

create permission from sobject metadata

# include sobject permission and all fields permission
sfdc coder:permission:build --sobject_dir ./src/objects --savefile ./src/permissionsets/dev_permission.permissionset --include_all_sobject_permission

# fieldPermissions
sfdc coder:permission:build --sobject_dir ./src/objects --savefile ./src/permissionsets/dev_permission.permissionset --fields Account.custom_field1 Account.custom_field2 Opportunity.custom_field1

list fields from sobject metadata directory

# list fields
sfdc coder:permission:list -t fields --sobject_dir ./src/objects

sfdc coder:permission:list -t fields --sobject_dir ./src/objects | grep Account

list sobject from sobject metadata directory

# list sobject
sfdc coder:permission:list -t sobject --sobject_dir ./src/objects

salesforce folder

# report folder
sfdc folder:list -n ReportFolder

# email folder
sfdc folder:list -n EmailTemplate

download salesforce attachment

download salesforce attachment(ContentVersion):

  • max limit size: 2000
  • default filename template: {Id}_{Title}_v{VersionNumber}.{FileExtension}
sfdc download:attachment --savedir tmp/download --filename "{Title}_v{VersionNumber}.{FileExtension}" --limit 2000

Ant Migration Tool

init Ant Migration Tool

sfdc ant:migration:tool
# or
sfdc ant:migration:tool -p .

tools

json format

cat $json_file_path | sfdc tools:json:format

sfdc tools:json:format -i $json_file_path

For developer

Set up docker

# for windows user
docker run --rm -it -v %cd%:/app -w=/app -e TZ=Asia/Tokyo --name sfdc-cli_developer_1 python:3.8 bash
# for linux/mac
docker run --rm -it -v `pwd`:/app -w=/app -e TZ=Asia/Tokyo --name sfdc-cli_developer_1 python:3.8 bash

# git clone
git clone https://github.com/exiahuang/sfdc-cli

# setup
cd sfdc-cli
pip3 install -r requirement.dev.txt
python3 -m sfdc_cli.cli
alias sfdc="python3 -m sfdc_cli.cli"
export PYTHONPATH="/app/sfdc-cli:$PYTHONPATH"
sfdc -h

# remove commmand
unalias sfdc

remove pycache

### use find
find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
### use py3clean
py3clean .

Run test case.

new project

python3 -m unittest tests.test_project

init from template

python3 -m unittest tests.test_metadata_template

sfdc metadata api

# new apex/trigger/page/component template
python3 -m unittest tests.test_metadata_template

# metadata api: new metadata
python3 -m unittest tests.test_metadata_api.MetadataApiNewMetaTestCase.test_metadata_new

# metadata api: reload cache
python3 -m unittest tests.test_metadata_api.MetadataApiNewMetaTestCase.test_metadata_cache

# metadata api: update metadata
python3 -m unittest tests.test_metadata_api.MetadataApiUpdateTestCase.test_metadata_update

# metadata api: update aura metadata
python3 -m unittest tests.test_metadata_api.MetadataApiUpdateTestCase.test_metadata_update_arua

# metadata api: refresh metadata
python3 -m unittest tests.test_metadata_api.MetadataApiRefreshTestCase

# metadata api: refresh aura metadata
python3 -m unittest tests.test_metadata_api.MetadataApiRefreshAuraTestCase

# metadata api: print attr
python3 -m unittest tests.test_metadata_api.MetadataApiAttrTestCase

# delete metadata
python3 -m unittest tests.test_metadata_api.MetadataApiDeleteTestCase

# test delete aura
python3 -m unittest tests.test_metadata_api.MetadataApiDeleteTestCase.test_metadata_delete_arua

# run testclass
python3 -m unittest tests.test_testclass.TestclassTestCase.test_run_test

# run retrieve apex coverage
python3 -m unittest tests.test_testclass.TestclassTestCase.test_retrieve_apex_coverage

# retrieve zip
python3 -m unittest tests.test_metadata_api.RetrieveApiTestCase

# package xml : retrieve from server
python3 -m unittest tests.test_package_xml.PackageXmlTestCase.test_package_xml_from_server

# package xml : build from local
python3 -m unittest tests.test_package_xml.PackageXmlTestCase.test_package_xml_from_dir

# open in browser
python3 -m unittest tests.test_browser.BrowserTestCase.test_open_src
python3 -m unittest tests.test_browser.BrowserTestCase.test_open_aura

# open in browser : open sobject
python3 -m unittest tests.test_browser.BrowserTestCase.test_open_account_sobject
python3 -m unittest tests.test_browser.BrowserTestCase.test_open_opp_sobject

sfdc file attribute

# file attr
# file attr
python3 -m unittest tests.test_metadata_api.FileAttrTestCase

result:

{
  "name": "MyApexController",
  "file_path": "project/sfdc-projcet1/src/classes",
  "file_name": "MyApexController.cls",
  "dir": "classes",
  "p_dir": "src",
  "extension": "cls",
  "metadata_type": "ApexClass",
  "metadata_folder": "classes",
  "metadata_sub_folder": "",
  "is_sfdc_file": true,
  "is_src": true,
  "is_lux": false,
  "is_lux_root": false,
  "is_lwc": false,
  "is_lwc_root": false,
  "lux_type": "",
  "lux_name": "",
  "file_key": "classes/MyApexController.cls"
}


{
  "name": "HelloWorld",
  "file_path": "project/sfdc-projcet1/src/aura/HelloWorld",
  "file_name": "HelloWorld.cmp",
  "dir": "HelloWorld",
  "p_dir": "aura",
  "extension": "cmp",
  "metadata_type": "AuraDefinition",
  "metadata_folder": "aura",
  "metadata_sub_folder": "HelloWorld",
  "is_sfdc_file": true,
  "is_src": false,
  "is_lux": true,
  "is_lux_root": false,
  "is_lwc": false,
  "is_lwc_root": false,
  "lux_type": "COMPONENT",
  "lux_name": "HelloWorld",
  "file_key": "aura/HelloWorld/HelloWorld.cmp"
}

package

python3 setup.py sdist
python3 setup.py bdist_wininst

py2exe build windows exe

py -3.4 -m venv .py34
.py34\Scripts\activate.bat
# python -m pip install --upgrade pip
pip install py2exe setuptools
pip install requests XlsxWriter
python -V
python setup.py py2exe

Acknowledgement

Basic on OpenSource

  1. xlsxwriter (License: BSD)
  2. Simple-Salesforce (License: Apache 2.0)
  3. requests (License: Apache 2.0)
  4. Apex Template From MavensMate