Skip to content

Latest commit

 

History

History
322 lines (206 loc) · 11.7 KB

README.md

File metadata and controls

322 lines (206 loc) · 11.7 KB

Sweet.apex

Sweet.apex is the next generation of Apex development, transpiling Sweet Apex(a feature-rich Apex-like code) to Apex classes.

Why Sweet.apex?

Have you ever dreamed of using custom annotations in Apex? Have you ever wondered if you could eliminate some Apex boilerplate codes? Sweet.apex is here to make your dreams come true, by providing some of the most amazing features right at your disposal.

Showtime

Before we move on, take a look at what Sweet.apex can do.

Not Null Validation

With @notNull, we can specify the parameter value is not null. Otherwise, assertion exceptions will be thrown.

public class NotNullDemo {
    public static Integer increment(@notNull Integer i) {
        return i + 1;
    }
}

Equals and HashCode Generation

With @identity, equals and hashCode are automatically generated for our Apex class.

@identity
public class IdentityDemo {
    private String name;
    private Integer id;
    private Boolean active;
}

Template String

With template strings, we no longer need to concatenate strings.

public class TemplateStringDemo {
    public static void run() {
        String name = 'Sweet.apex';
        Integer count = 0;
        String result = `Greeting ${name} for ${count} time(s)`;
    }
}

Rethrow Exceptions

With @rethrow, we can catch any exception thrown from this method and rethrow it in a wrapped exception, particularly useful in Salesforce Lightning server controllers.

public class RethrowDemo {
    @AuraEnabled
    @rethrow(AuraHandledException)
    public static String getMessage() {
        // Custom code
        throw new DmlException('For Demo Purpose');
        // Custom code
        return null;
    }
}

Collection Casting

Casting between collections in Apex is hard, but Sweet.apex makes it easy.

public class CastingDemo {
    public static void main() {
        Set<Object> set1 = new Set<Object>{ 'a', 'b' };
        Set<String> set2 = (Set<Object> => Set<String>)set1;
    }
}

Custom Operators

Want to define custom operators? Go ahead.

public class OperatorDemo {
    @operator
    public static Integer add(Integer a, Integer b) {
        return a + b;
    }

    public static void main() {
        Integer a = 1;
        Integer b = 2;
        System.debug(a add b);
    }
}

Take a Breath

When you read here, you might already have one question in mind. Is this real Apex code?

Yes and no.

Technically speaking, they are Sweet Apex codes, cousins of Apex codes, yet with more powers. In some way, they are equivalent to Apex codes, and we will see shortly.

Well, the code snippets above are just starters. We have much more fascinating main courses afterwards, but we are not going to show them here, as this is intended for us to get started. If you want to check it out, visit our documentation site for details.

Inspirations

Before we reveal the secret of Sweet.apex, we would like to introduce one important Salesforce technique, SFDX. This is a developer-friendly command line tool that helps us do lots of things and creates many possibilities. Without DX, it would be nearly impossible to deploy our Apex code directly from locally to our Orgs. Yes, SFDX paves the way for building a brand-new development process, and let's take a closer look at this.

The time when we used to edit Apex files in the Salesforce console has long gone and now we can work locally on these files before deploying them using SFDX. Deploying Apex files has never been easier. Take that advantage to its best and keep on.

The Apex classes are the only acceptable source codes for Salesforce, but not for us. We can make any files as our source files, as long as they can be transformed into Apex classes in some way(Deploying Apex classes is so easy that we can simply ignore its impact). And this is where we got the inspirations.

This innovating source file can be of any kind, with any features, only if it can be converted to Apex classes. To make things easier, we adopt similar grammar with Salesforce Apex in this source file and name it the Sweet Apex file.

Sweet Apex files are bridged to Apex classes by one technique, transpilation, which is a process to compile from one kind of source file to another kind. Simply put, we transpile Sweet Apex codes into Apex classes, then deploying them by SFDX.

Getting Started

Big Picture

Knowing what transpilation is, you still need to grasp the big picture of how we are developing Apex codes now. We are not working directly on Apex codes. Instead, we are writing Sweet Apex codes, and then run a transpilation process to turn them into Apex codes before we deploy them. Keep this in mind and get your hands wet with the real Sweet Apex.

Installation

Sweet.apex is a JavaScript project based on node.js. Make sure you have node.js and npm installed before you go on.

Clone the project from the github repo, go to the root of the project and run the command.

npm install

Wait until the installation is finished.

Write First Sweet Apex

Go to any directory(/Users/wilson/sweet_apex/src, for example), and write a simple Sweet Apex file.

public class HelloSweetApex {
    public static void main() {
        Integer a = 5;
        Integer b = 7;
        System.debug(a % b);
    }
}

Well, this is simple. But be careful. This file won't compile in Apex, because % is not supported. However, we are writing Sweet Apex files, and we will see what will happen.

Transpile It

Let's say you want to build your Sweet Apex files into a directory called /Users/wilson/sweet_apex/build. Run the following command in the root of the project.

node transpile.js /Users/wilson/sweet_apex/src /Users/wilson/sweet_apex/build

Wait until it says it's completed.

Transpiled Apex Class

Go to /Users/wilson/sweet_apex/build and check what has been generated. You can find a file called HelloSweetApex.cls, and it looks like this:

public class HelloSweetApex {
    public static void main() {
        Integer a = 5;
        Integer b = 7;
        System.debug(Math.mod(a, b));
    }
}

Note that a % b has been translated to Math.mod(a, b). This is a typical example of how Sweet Apex codes are transpiled to Apex codes.

Deploy and Check

The next thing is definitely running your DX tools to deploy the code to your Org and check if it actually works.

Features

Currently, Sweet.apex supports the following features:

Convert a method to an Action. For more details on Action, please check Action.apex

Generate simple JSON files representing Sweet Apex class structures and comments, which can be further used to create pretty documentation sites.

Simplify how you create lists and maps.

Adopt aspects before and after your method invocations. Check AOP(Aspect Oriented Programming) for details.

Cast between collections of different lists, sets and maps.

Specify the default value of method parameters.

Create enums that have custom methods.

Build files to static resources.

Convert methods to functions. Check R.apex for more details on Funcs.

Generate equals and hashCode methods.

Inject beans to variables. Check DI(Dependency Injection).

Convert lambda expressions to anonymous functions.

Create logger object for the class. Check Log.apex for details.

Support modulo operator %.

Assert method parameters are not null.

Define custom operators from static methods.

Create methods that support optional parameters.

Add reflection behavior to the class.

Catch any exception thrown from the method and rethrow it with a wrapped one.

Support switch-case syntax.

Support custom code template.

Avoid concatenating strings.

Generate JavaScript equivalent functions from Apex methods.

Add custom tags to prefix strings.

Add support for defining custom annotations on classes.

Specify a nullable variable to avoid null de-reference.

Infer the variable type according to the context.

Infer the variable type according to the context and make it final.

Add array access support to maps.

Help generate constructors.

Generate transactional methods that roll back when an exception is thrown.

Destructure the list/map/sobject.

Import static fields and methods from classes.

Combine Func calls into pipelines.

Support var-args parameter in methods.

Support patching methods to a type.

Import a type as an alias.

Feature Request

If you have any feature request, you can submit it in the issues. Or you can submit a PR to implement your own feature.