Pack.apex is a tool to help you generate Func wrappers for existing Apex classes.
Sometimes when we want to convert an existing Apex API into a Func, we have to manually create a custom Func to implement that. With Pack.apex, you can easily generate Func wrappers according to your selected Apex APIs.
Pack.apex has a dependency over R.apex
Please include it before including Pack.apex.
You can include the necessary Apex class files located in the 'src/classes'.
Or you can make customizations and generate the Apex class files before including them.
Pack.apex is actually a node-js CLI application that generates the Func wrapper Apex class for you. What you need is the generated Apex class, Pack.cls
, which can be further imported to your Org, and used like this:
String userId = (String)Pack.UserInfoCls.getUserId.run();
String userName = (String)Pack.UserInfoCls.getUserName.run();
Here UserInfo.getUserId()
is wrapped into a Func Pack.UserInfo.Cls.getUserId
, and invoked by calling run
. So is it with UserInfo.getUserName()
.
By default, Pack.apex has already converted most of Salesforce Apex APIs in the namespace of System
.
If you want to use a Func of TypeName.MethodName
, you can refer to Pack.TypeNameCls.MethodName
. If the MethodName
is a reserved word, use Pack.TypeNameCls.MethodNameFn
instead. For example,
List<Object> mList = new List<Object>{ 3, 2, 1};
Pack.ListCls.sortFn.run(mList);
We can run the CLI application to generate Pack.cls
at any time.
First we need to initialize our project. Run the code at the root of the project after you have installed node and npm.
npm install
Run this, which will start to generate Pack.cls
.
node generator.js
By default, Pack.apex will read from src/packs
and write generated Apex files into src/classes
.
The Pack.cls
is generated from the source pack files. Here is a sample pack file.
constructor List<Object> :: ()
add :: Object -> void
Each method is specified in one line.
The first word before ::
is the method name. If it is a static method, static
is appended before its name. If it is a constructor, constructor
is appended before its name and the name is the concrete type name.
The string after ::
is the functionally annotated method signature. Generally speaking, a -> b -> c
represents a function that takes (a, b)
and returns c
.
Pack.apex will load the source pack files and generate corresponding Funcs.
Sometimes what Pack.apex generates is not what we want, and we can override the generated code by providing our own version, which is placed in hack files.
Here is a hacking code from List_getSObjectType.hack
, which hacks the getSObjectType
method of List
into this.
else if(funcName == 'getSObjectType' && nthArg(args, 1) instanceof List<Object>) {
List<SObject> mList = (List<SObject>)R.toSObjectList.run(nthArg(args, 1));
return mList.getSObjectType();
}
You can customize how to generate Pack.cls
by providing your own configuration in config.json
in the root of the project.
The default configuration looks like this:
{
"srcDir": "src/packs",
"destDir": "src/classes",
"packFileSuffix": ".pack",
"hackFileSuffix": ".hack",
"constructorPrefix": "constructor ",
"staticPrefix": "static ",
"apexClassName": "Pack",
"reservedWords": [ ... ],
"comment": "// Generated by Pack.apex. Please do not modify this file.",
"metaFile": "meta.xml",
"generateFuncPackage": true,
"generateTestClass": true,
"skipTestCases": [ ... ]
}
Here are the details about the configuration items.
Key | Description |
---|---|
srcDir | The source directory where .pack/.hack files are located |
destDir | The destination directory where Pack.cls is generated to |
packFileSuffix | The suffix of the pack file, '.pack' by default |
hackFileSuffix | The suffix of the hack file, '.hack' by default |
constructorPrefix | The prefix used to indicate the constructor, 'constructor ' by default |
staticPrefix | The prefix used to indicate the static method, 'static ' by default |
apexClassName | The generated main Apex class name, 'Pack' by default |
reservedWords | The reserved key words from Salesforce apex |
comment | The comment in the generated files |
metaFile | The path of the meta data xml file |
generateFuncPackage | Whether to generate Func Package, true by default |
generateTestClass | Whether to generate test classes, true by default |
skipTestCases | The list of apex class names whose test cases will be skipped |