Home Blog

How to Utilize Salesforce CLI sf (v2)

Table of Contents

Introduction

The Salesforce CLI is not just a tool; it’s the cornerstone of development on the Salesforce Platform. It’s your go-to for building, testing, deploying, and more. As one of the most important development tools in our ecosystem, it’s a daily companion for Salesforce Developers. Its role in DevOps practices, such as continuous integration, is fundamental. Now, after seven years of general availability, we’re stepping into a new era for the Salesforce CLI.

Embrace the future

This is the way forward for Salesforce Developers. You will thank Salesforce for making this command more powerful and faster. The installation and update times are also significantly less. It is more capable and simpler to remember. Furthermore, there will be new plugins and features for the new version of Salesforce CLI sf(v2)

What's changed

First of all, the prefix of the command has been changed from `sfdx` to `sf`. The flags are also more intuitive and easier to remember. For example to create a scratch org earlier, you used to make commands like the below:

ravigrover@Ravis-MacBook-Pro ApexDebuggerProject % sfdx force:org:create -f config/project-scratch-def.json -a MyScratchOrg
Warning: The force:org:create command is deprecated. Try “org create scratch” or “org create sandbox” instead.
Warning: Record types defined in the scratch org definition file will stop being capitalized by default in a future release.
Set the `org-capitalize-record-types` config var to `true` to enforce capitalization.
Successfully created scratch org: 00DHE000000Q32H2AS, username: test-zc1afdvpvqmz@example.com.
ravigrover@Ravis-MacBook-Pro ApexDebuggerProject %

Now, with sf-style commands coming into the picture, see how easy it is to remember the clauses and no need to use a colon after each word in the command like below:

ravigrover@Ravis-MacBook-Pro ApexDebuggerProject % sf org create scratch –target-dev-hub apxdbgrdevhub –definition-file config/project-scratch-def.json –set-default –duration-days 3

Warning: Record types defined in the scratch org definition file will stop being capitalized by default in a future release.
Set the `org-capitalize-record-types` config var to `true` to enforce capitalization.
Creating Scratch Org…
RequestId: 2SRdL0000000TEvWAM (https://capgeminiaustralia27-dev-ed.develop.my.salesforce.com/2SRdL0000000TEvWAM)
OrgId: 00DC10000013PhF
Username: test-ayuqfpdf4b8x@example.com
✓ Prepare Request
✓ Send Request
✓ Wait For Org
✓ Available
✓ Authenticate
✓ Deploy Settings
Done

Your scratch org is ready.

Also, it is noteworthy here that new features and fixes will be going only to sf instead of sfdx, but having said that, you can still use old sfdx-style commands. Look at this example to see how commands have become more intuitive and easier to remember below:

ravigrover@Ravis-MacBook-Pro ApexDebuggerProject % sfdx force:source:push
Warning: We plan to deprecate this command in the future. Try using the “project deploy start” command instead.
Pushing v59.0 metadata to test-ayuqfpdf4b8x@example.com using the v60.0 SOAP API.
DEPLOY PROGRESS | ████████████████████████████████████████ | 14/14 Components
Updating source tracking… done

=== Pushed Source

STATE   FULL NAME            TYPE                     PROJECT PATH                                                                    
─────── ──────────────────── ──────────────────────── ────────────────────────────────────────────────────────────────────────────────
Created AccountService       ApexClass                force-app/main/default/classes/AccountService.cls                               
Created AccountService       ApexClass                force-app/main/default/classes/AccountService.cls-meta.xml                      
Created AccountServiceTest   ApexClass                force-app/main/default/classes/AccountServiceTest.cls                           
Created AccountServiceTest   ApexClass                force-app/main/default/classes/AccountServiceTest.cls-meta.xml

With sf executable, same command will look like below:

 

ravigrover@Ravis-MacBook-Pro ApexDebuggerProject % sf project deploy start
Deploying v59.0 metadata to test-ayuqfpdf4b8x@example.com using the v60.0 SOAP API.
Deploy ID: 0AfC1000004L5gjKAC
Status: Succeeded | ████████████████████████████████████████ | 1/1 Components | Tracking: 4/4

Deployed Source
==========================================================================================================
| State   Name       Type                     Path                                                        
| ─────── ────────── ──────────────────────── ────────────────────────────────────────────────────────────
| Created demoLWCOne LightningComponentBundle force-app/main/default/lwc/demoLWCOne/demoLWCOne.html       
| Created demoLWCOne LightningComponentBundle force-app/main/default/lwc/demoLWCOne/demoLWCOne.js         
| Created demoLWCOne LightningComponentBundle force-app/main/default/lwc/demoLWCOne/demoLWCOne.js-meta.xml 

Get started with Salesforce CLI sf (v2)

To try the new command style, you have to uninstall sfdx. The instructions are here.

To determine the equivalent commands from sfdx style to sf style, please refer to this resource. Besides simply switching the name of the executable from sfdx to sf, there are a number of changes that apply to CLI commands when upgrading your projects. The Salesforce CLI documentation provides a good overview of these changes.

Legacy sfdx style command

Equivalent sf-style command

Comments

sfdx force:org:delete -p -u recipes

sf org delete scratch -p -o recipes

The scratch subcommand needs to be added.

The target org flag changes from -u to -o.

sfdx force:org:create -s -f config/project-scratch-def.json -d 30 -a recipes

sf org create scratch -d -f config/project-scratch-def.json -y 30 -a recipes

The scratch subcommand needs to be added.

The “assign default org” flag changes from -s to -d.

The scratch org duration flag changes from -d to -y.

sfdx force:source:push

sf project deploy start

This is a significant change, but the new command works for all project formats (source or metadata).

Previously, you needed distinct commands.

sfdx force:user:permset:assign -n recipes

sf org assign permset -n recipes

The topic changes from user to org and the order of the sub commands changes.

sfdx force:data:tree:import -p data/data-plan.json

sf data import tree -p data/data-plan.json

Imports the data from plan.json

sfdx force:org:open -p lightning/n/Hello

sf org open -p lightning/n/Hello

Opens the component in the org

sfdx force:apex:test:run -c -r human -w 20

sf apex test run -c -r human -w 20

Sets the execution of test classes

Closing words

To conclude this short overview of the migration from sfdx-style commands to sf-style commands, you will be more likely to remember the wordings of every command since sf-style commands are more like human language and easier to write.

Resources

Salesforce CLI GitHub repository for checking out the source code or the release notes, leaving feedback and, reporting issues

Must Read

Save the day of a Developer with Apex Log Analyzer

Table of Contents

What is Apex Log Analyzer?

Apex Log Analyzer, a tool designed with Salesforce developers in mind, is here to simplify and accelerate your performance analysis. With its intuitive Flame charts and Call Trees, you can effortlessly visualise code execution, gaining clear insights into the flow and performance of your code. This powerful tool also features Method and Database Analysis, which helps in identifying and resolving performance issues, as well as SOQL and DML problems.

By highlighting inefficiencies and bottlenecks, Apex Log Analyzer empowers you to optimise your code more effectively, ensuring smoother and more reliable application performance. Integrating this tool into your development workflow can save valuable time, enhance productivity, and improve overall code quality.

Getting Started with Apex Log Analyzer

  1. Installation: Apex Log Analyzer is included with the Salesforce Extension Pack or can be downloaded separately from the Visual Studio Code Marketplace. Ensure you have it installed to unlock its powerful capabilities.
  2. Execute Apex Code: Run the Apex code from which you wish to gather insights. This will generate the necessary debug logs for analysis.
  3. Gather Debug Logs: Collect the debug logs generated during the execution of your Apex code. These logs contain the detailed execution information required for analysis.
  4. Open and Analyze Logs: Open the debug log in Visual Studio Code. Right-click on the log and select ‘Log: Show Apex Log Analysis’ or click the option displayed at the top of the Apex debug log.
  5. View Results: With Apex Log Analyzer, the analysis is performed in the background, and the results are displayed in a new tab. This tab is filled with numerous interactive elements, providing the diagnostic information you need to save the day as a developer. This powerful tool highlights performance issues, SOQL/DML problems, and more, enabling you to optimise your code efficiently. By automating the analysis process, Apex Log Analyzer saves you valuable time, relieving the stress of manual code optimisation.

Understanding Apex Logs

Apex debug logs provide a detailed record of the execution flow of your Apex code, capturing events such as method invocations, database operations (SOQL/DML), and system debug statements. They reveal your code’s performance and behaviour, highlighting issues like CPU time consumption and memory usage.

By analysing these logs, developers can identify inefficiencies and pinpoint the exact location of errors, enabling more effective troubleshooting and optimisation.

Common Use Cases

We can all relate to this common scenario where we are expected to find the cause of bottlenecks in the application’s performance due to the code we recently pushed to meet the delivery schedule. However, it is causing the application to crawl at a snail’s pace. To illustrate this, I created three Apex classes with their respective methods, which are better than each other relatively.

Then I made them run in my developer edition org and analysed the logs to see what insights it gathered for me to present my tech lead with the cause of slowness and any solutions or workaround we can find. You will be surprised to see that it actually tells us the time in milliseconds visually in various colours so that anyone can deduce the crux of the matter and start planning the next steps for resolution.

Here is the sample code and how I ran it:

				
					public class InefficientClass {
    public static void inefficientMethod() {
        // Simulating an inefficient operation: Nested loops causing high CPU usage
        Integer result = 0;
        for (Integer i = 0; i < 1000; i++) {
            for (Integer j = 0; j < 1000; j++) {
                result += i * j;
            }
        }
        System.debug('Result: ' + result);
    }
}
				
			
				
					public class EfficientClass {
    public static void efficientMethod() {
        // Optimized operation: Single loop with more efficient computation
        Integer result = 0;
        for (Integer i = 0; i < 100000; i++) {
            result += i * 2;  // Simplified operation
        }
        System.debug('Result: ' + result);
    }
}
				
			
				
					public class LighterClass {
    public static void lighterMethod() {
        // Optimized operation: Direct computation without unnecessary loops
        Integer n = 1000000;
        Integer result = (n * (n - 1)) / 2;
        System.debug('Result: ' + result);
    }
}


				
			

Once the above Classes are deployed to the org, now is the time to run all of them in one go so that the Log Analyzer can gather the stats and show in one unit of work with times taken by each method.

				
					// Execute the inefficient method
InefficientClass.inefficientMethod();

// Execute the efficient method
EfficientClass.efficientMethod();

// Execute the lighter method
LighterClass.lighterMethod()
				
			

Now is the time to run the open command palette, run

				
					sfdx turn on apex debug logs
				
			

Which will start collecting and recording for the next 30 minutes by default. Then run

				
					sfdx get debug logs
				
			

which should open the Apex Debug Log. Now is the time for the moment of truth! Hit the

				
					Log: Show Apex Log Analysis
				
			

Written at the top of an Apex Debug Log file you will start seeing the visual analysis with meaningful information about SOQL and DMLs done if there were any in your apex code. In this case, I realised that lighterMethod was a simpler version of all the other versions I wrote since it was the fastest and took less than 0.2 ms. On the other hand, efficientMethod took 1367ms whereas inefficientMethod took 13855ms.

That was the call tree’s output, but the Analysis tab is even better since it shows the Total Time needed, which is around 15000 ms.

Conclusion

Apex Log Analyzer is a game-changer for Salesforce developers, turning the often daunting task of debugging and performance analysis into a more manageable and even enjoyable experience. By providing a clear, visual representation of code execution through Flame charts and Call Trees, it demystifies complex logs and brings hidden issues to light. The ability to quickly identify and resolve performance bottlenecks, SOQL/DML inefficiencies, and other critical problems means that developers can spend less time troubleshooting and more time building robust, efficient applications.

The satisfaction of pinpointing the exact cause of a bottleneck and optimising the code brings a genuine smile to a developer’s face, making their job less stressful and more rewarding.

In essence, Apex Log Analyzer truly saves the day by enhancing productivity, improving code quality, and empowering developers to deliver top-notch solutions with confidence and ease.

Resources

Salesforce PodCast

Introduction

Hey Everyone,

Welcome to my podcast, the first-ever podcast in India for Salesforce professionals.

Achievement

We are happy to announce that we have been selected as Top 15 Salesforce Podcasts.

Here is the link for the same: https://blog.feedspot.com/salesforce_podcasts/

Episodes

We have completed 13 Episodes so far and all episodes are here https://anchor.fm/sfdcpanther

Latest Episode

If you are interested in a Mock Interview then Please send your resume to us at contact@pantherschools.com

Stay Tuned for more updates

Salesforce Short Codes

Hello Awesome Developers/Admins,

On this page, I am going to update all the small reusable utilities which will be useful for any developer or admin.

Link to Repo

Here is the Link to GitHub Repo where you can find all the codes.

https://github.com/amitastreait/Salesforce-Short-Hands

I am excited to share that I have developed the salesforce utilities which are useful for any developer or organization. Here is the list of all the utilities which are available so far.

  1. Custom File Upload
  2. Custom Lookup
  3. Custom Error Handling Framework
  4. Some components related to Flows
  5. Generic DataTable using Field Set and Custom Metadata
  6. Extend Lightning DataTable to use Lookup, Picklist, and FileUpload component
  7. Custom Rating Component

Contribute to Repo

I will be very happy if you have any ideas and you wanted to share then please feel free to share your utilities with me.

You can find all the instructions here.

Your 3-Month Journey to Salesforce Developer Confidence

Table of Contents

Have you ever dreamt of customising Salesforce to fit your company’s custom requirements? You have the power within you – and it only takes a dedicated 30 minutes a day for three months. By staying consistent and dedicated to learning and applying Salesforce’s Apex programming language, you can evolve into a confident Salesforce developer, ready to tackle any project assignment.

Small changes lead to Big Wins

Forget the all-nighters and information overload. Consistent, focused practice is the key to mastering Apex. Spend just 30 minutes each day exploring a new Apex concept or tackling a hands-on coding challenge on platforms like Trailhead. This consistent approach over 3 months ensures the knowledge sticks and builds momentum. Imagine the surge of confidence you’ll feel when you automate a complex workflow – that’s the power you’re building!

The Trailblazer Community: Your Cheerleading Squad

The Salesforce community is a vibrant online haven filled with enthusiastic and supportive Trailblazers (Salesforce developers). Don’t be afraid to ask questions, share your Apex victories (big or small!), and learn from the experiences of others. Feeling stuck on a trigger? The Trailblazer community is there to help! You’ll be amazed at how quickly your confidence grows as you collaborate and learn from fellow developers.

Ready to Claim Your Salesforce Developer Confidence?

The time to unlock your inner Salesforce whiz is now! Dedicate just 30 minutes a day for the next 3 months to learning Apex and watch your confidence soar. Remember, the journey to becoming a Salesforce developer is about progress, not perfection. So, take the first step today and join the ranks of those who wield the power of the cloud!

Resource

How to start your AI Journey?

0

Table of Contents

Introduction

Are you tired of the same old world? Do you dream of painting landscapes with your code, composing symphonies with data, or crafting stories that dance with reality itself? Then open your mind to the enchanting realm of Generative AI! ✨

The Prerequisites

The Learning Landscape:

Now, let’s explore our options

The Secret Weapon: Prompt Engineering: 🪄

Crafting the perfect prompt is like whispering secret instructions to your AI muse. But there’s no one-size-fits-all approach! Exploring different types of prompts unlocks a spectrum of possibilities in your Generative AI creations. Here’s a sneak peek:

Learn more about prompt engineering from the below link https://www.pantherschools.com/the-secret-weapon-prompt-engineering/

Points to remember while writing prompt

  • Use clear and concise language in prompts.
  • Provide relevant context and data.
  • Adjust temperature for creativity or accuracy.
  • Experiment with different prompt formats and lengths.
  • Integrate model responses into Salesforce workflows using provided APIs.

The Secret Weapon: Prompt Engineering: 🪄

0

Table of Contents

Introduction

Crafting the perfect prompt is like whispering secret instructions to your AI muse. But there’s no one-size-fits-all approach! Exploring different types of prompts unlocks a spectrum of possibilities in your Generative AI creations. Here’s a sneak peek:

Different Types of Prompt Engineering

1. The Classic Prompt: ✍️

  • Straightforward and clear, laying out the desired task or output.
  • Think: “Write a poem about a robot falling in love with the moon.”
  • Ideal for beginners and specific, focused tasks.

2. The N-Shot Prompt:

  • Provide a few examples (N) of the desired output to guide the AI.
  • Imagine: “Show me 3 examples of poems about nature written in free verse, then write your own.”
  • Useful for refining style and direction, fostering consistency.

3. The Chain-of-Thought Prompt:

  • Break down complex tasks into smaller, sequential steps.
  • Picture: “1. Identify emotions in this image. 2. Generate captions expressing those emotions in different tones. 3. Merge captions into a cohesive paragraph.”
  • Perfect for tackling intricate tasks, and promoting logical flow.

4. The Conditioned Prompt:

  • Sets specific constraints or parameters to shape the output.
  • Think: “Write a children’s story filled with puns, but avoid using clichés.”
  • Adds a layer of challenge and control, encouraging creative exploration within boundaries.

5. The Open-Ended Prompt:

  • Offers minimal guidance, leaving the AI to fill in the blanks.
  • Imagine: “Create a world where animals speak and build cities. Tell me a story about its most daring explorer.”
  • Sparks innovation and unexpected results, ideal for brainstorming and discovery.

6. Interactive Prompts:

  • Leverage user input or external data to dynamically adjust the narrative.
  • Picture: “You are a detective in a cyberpunk city. Tell me what you see as I describe the crime scene.”
  • Creates an immersive, personalized experience, blurring the lines between creator and creation.

Points to remember while writing prompt

  • Use clear and concise language in prompts.
  • Provide relevant context and data.
  • Adjust temperature for creativity or accuracy.
  • Experiment with different prompt formats and lengths.
  • Integrate model responses into Salesforce workflows using provided APIs.

Examples of Different Prompts

Classic Insight Prompt

Prompt: Analyze historical sales data of tech clients and identify key trends in purchasing behaviour.

				
					// Query tech client sales data
List<Opportunity> techSales = [
    SELECT Id, CloseDate, Amount, Product.Name
    FROM Opportunity
    WHERE AccountId IN (SELECT Id FROM Account WHERE Industry = 'Technology')
    AND IsClosed = true
    ORDER BY CloseDate DESC
];

// Calculate quarterly sales trends
Map<Date, Decimal> quarterlySales = new Map<Date, Decimal>();
for (Opportunity opp : techSales) {
    Date quarterStart = Date.newInstance(opp.CloseDate.year(), opp.CloseDate.month() - opp.CloseDate.month() % 3, 1);
    quarterlySales.put(quarterStart, quarterlySales.get(quarterStart) + opp.Amount);
}

// Identify top products by revenue
Map<String, Decimal> productRevenue = new Map<String, Decimal>();
for (Opportunity opp : techSales) {
    productRevenue.put(opp.Product.Name, productRevenue.get(opp.Product.Name) + opp.Amount);
}

// Display insights for developers to interpret
System.debug('Quarterly Sales Trends: ' + quarterlySales);
System.debug('Top Products by Revenue: ' + productRevenue);

				
			

Personalized Customer Prompt

Prompt: Recommend three relevant products for Customer X based on recent website visits and past purchases.

				
					// Gather customer data
Contact customerX = [SELECT Id, Name, RecentVisitedPages, PastPurchases FROM Contact WHERE Name = 'Customer X'];

// Collect product recommendations from Einstein (replace with your actual Einstein model)
List<ProductRecommendation> recommendations = EinsteinRecommendations.getRecommendationsForContact(customerX);

// Display top 3 recommendations
System.debug('Recommended Products for Customer X:');
for (Integer i = 0; i < 3; i++) {
    System.debug('- ' + recommendations[i].Product.Name);
}

				
			

Data-Driven Content Prompt

Prompt: Create a blog post addressing top customer concerns from surveys and support tickets.

				
					// Gather customer feedback data
List<Case> supportTickets = [SELECT Id, Subject, Description FROM Case WHERE Status = 'Closed' AND Type = 'Problem'];
List<SurveyResponse> surveyResponses = [SELECT Id, Question, Answer FROM SurveyResponse];

// Extract common topics and concerns
Set<String> topConcerns = new Set<String>();
for (Case ticket : supportTickets) {
    topConcerns.addAll(extractKeywords(ticket.Subject, ticket.Description));
}
for (SurveyResponse response : surveyResponses) {
    topConcerns.addAll(extractKeywords(response.Question, response.Answer));
}

// Generate blog content
String blogPost = '**Top Customer Concerns and How We're Addressing Them**\n\n';
for (String concern : topConcerns) {
    blogPost += '* **' + concern + ':**\n';
    blogPost += '    - Explanation of the concern\n';
    blogPost += '    - Steps we're taking to address it\n';
}

// Display blog post for developers to review and publish
System.debug(blogPost);

				
			

Predictive Scenario Prompt

Prompt 1: Predict the likelihood of a lead converting to an opportunity based on historical data and current lead attributes.

				
					public class LeadConversionPredictor {

    public PredictionResult predictLeadConversion(Lead lead) {
        // 1. Gather historical data for lead conversion analysis
        List<Lead> historicalLeads = [SELECT Id, ConvertedDate, ... FROM Lead WHERE ...];
        // 2. Train a prediction model (e.g., logistic regression, decision tree)
        Model model = trainPredictionModel(historicalLeads);
        // 3. Extract relevant lead attributes
        Map<String, Object> leadFeatures = extractLeadFeatures(lead);
        // 4. Generate prediction using the model
        Probability prediction = model.predict(leadFeatures);
        // 5. Return prediction result
        return new PredictionResult(prediction);
    }

    // Helper methods for model training and feature extraction
    private Model trainPredictionModel(List<Lead> leads) {
        // Implement model training logic
    }

    private Map<String, Object> extractLeadFeatures(Lead lead) {
        // Map lead attributes to features for the model
    }
}

				
			

Prompt 2: Identify customers most likely to churn within the next 6 months, considering past purchase patterns, engagement metrics, and support interactions.

				
					public class ChurnPredictor {

    public List<Customer> predictHighChurnRiskCustomers() {
        // 1. Gather relevant customer data from multiple objects
        List<Customer> customers = [SELECT Id, ... FROM Customer];
        List<Order> orders = [SELECT Id, CustomerId, ... FROM Order];
        List<Case> cases = [SELECT Id, CustomerId, ... FROM Case];
        // 2. Calculate churn risk scores based on defined criteria
        Map<Id, Decimal> churnScores = calculateChurnScores(customers, orders, cases);
        // 3. Identify customers with scores above a threshold
        List<Customer> highChurnRiskCustomers = new List<Customer>();
        for (Customer customer : customers) {
            if (churnScores.get(customer.Id) > churnThreshold) {
                highChurnRiskCustomers.add(customer);
            }
        }
        return highChurnRiskCustomers;
    }

    // Helper method for churn score calculation
    private Map<Id, Decimal> calculateChurnScores(List<Customer> customers, List<Order> orders, List<Case> cases) {
        // Implement churn score logic
    }
}

				
			

N-Shot Prompt

Prompt:

Generate a list of 3 email subject lines that are likely to get high open rates, based on the following examples:

  • Example 1: Your free trial is about to expire!
  • Example 2: Don’t miss out on this exclusive offer!
  • Example 3: 5 secrets to boosting your sales productivity

Response

  1. “Unlock VIP Access: Special Benefits Await You!”
  2. “Flash Sale Alert: Limited-time Savings Inside!”
  3. “Double Your Productivity with These Proven Strategies!”

Prompt: Write an Apex trigger that updates the ‘Last_Reviewed_Date’ field on the Account object to today’s date whenever a new Opportunity is created for that account.

				
					trigger UpdateContactLastContactedDate on Contact (after insert) {
    for (Contact c : Trigger.new) {
        c.Last_Contacted_Date__c = Date.today();
    }
}

				
			

Few Short Example

Prompt: Write an Apex method that calculates the total amount of all open opportunities for a given account, using only a few keywords as guidance: account ID, opportunity amount, and open opportunities.

Keywords:

  • account ID
  • opportunity amount
  • open opportunities
				
					public static Decimal calculateTotalOpenOpportunityAmount(Id accountId) {
    List<Opportunity> openOpps = [
        SELECT Amount
        FROM Opportunity
        WHERE AccountId = :accountId AND IsClosed = false
    ];

    Decimal totalAmount = 0;
    for (Opportunity opp : openOpps) {
        totalAmount += opp.Amount;
    }

    return totalAmount;
}

				
			

Resources

Exploring the world of prompt engineering can be exhilarating and empowering. To ignite your journey, here’s a curated list of resources and links to help you learn and master this fascinating skill:

Interactive Platforms:

Comprehensive Guides:

Blogs and Articles:

Online Courses:

Community and Discussion:

5/5

Stuck in coding limbo?

Our courses unlock your tech potential