diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index 6e4aa685..1e5a8a27 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -138,14 +138,14 @@ jobs: - name: 'Authenticate Dev Hub' run: sf org login sfdx-url -f ./DEVHUB_SFDX_URL.txt -a devhub -d - # Create prerelease scratch org - - name: 'Create prerelease scratch org' - if: ${{ env.IS_PRERELEASE }} - run: sf org create scratch -f config/project-scratch-def.json -a scratch-org -d -y 1 --release=preview + # # Create prerelease scratch org + # - name: 'Create prerelease scratch org' + # if: ${{ env.IS_PRERELEASE }} + # run: sf org create scratch -f config/project-scratch-def.json -a scratch-org -d -y 1 --release=preview # Create scratch org - name: 'Create scratch org' - if: ${{ !env.IS_PRERELEASE }} + # if: ${{ !env.IS_PRERELEASE }} run: sf org create scratch -f config/project-scratch-def.json -a scratch-org -d -y 1 # Deploy source to scratch org diff --git a/.gitignore b/.gitignore index 929f49b4..64c3342d 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,5 @@ $RECYCLE.BIN/ .pmdCache /IlluminatedCloud/ApexKit_Company/OfflineSymbolTable.zip /force-app/main/default/profiles/*.profile-meta.xml -pmd/pmd.csv /.idea/sonarlint/ /pmd/*.csv diff --git a/config/project-scratch-def.json b/config/project-scratch-def.json index 6cd8a7d9..5fd23329 100644 --- a/config/project-scratch-def.json +++ b/config/project-scratch-def.json @@ -2,7 +2,6 @@ "orgName": "ApexKit Company", "description": "ApexKitV2.5", "edition": "Developer", - "hasSampleData": true, "features": [ "EinsteinGPTForDevelopers", diff --git a/docs/Tuple.md b/docs/Tuple.md new file mode 100644 index 00000000..a5869509 --- /dev/null +++ b/docs/Tuple.md @@ -0,0 +1,162 @@ +`APIVERSION: 58` + +`STATUS: ACTIVE` + +Tuple represents a key-value pair. Kinda. Don't come at me math nerds. +You may be asking why this exists, given the existence of Map. Unfortuately Map isn't available everywhere. +Notably, it's not available in Apex-defined Data Types used by Flow/Invocable actions. +Additionally, `Object` is not a valid data type in Apex-defined Data Types, so we can't use a list of objects +that have a string key, and Object value. This is the next best thing. A kind of polyfill for Map<String,Object> +for use in Apex-defined Data Types. +See also: https://help.salesforce.com/s/articleView?id=sf.flow_considerations_apex_data_type.htm&type=5 +Available primitive datatypes available for use in tuple: +Boolean, Integer, Long, Decimal, Double, Date, DateTime, and String. Single values and lists are supported for each data type. + +## Constructors + +### `public Tuple()` + +`SUPPRESSWARNINGS` + +In order to create a Tuple instance from within a flow, you need a no-arg constructor. + +### `public Tuple(String key, Object value)` + +standard constructor accepting a key and value + +#### Parameters + +| Param | Description | +| ------- | ----------------------------------- | +| `key` | String the name of the Tuple's Key. | +| `value` | Object the Tuple's Value. | + +--- + +## Fields + +### `public booleanValue` → `Boolean` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public booleans` → `Boolean` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public dateTimeValue` → `Datetime` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public dateValue` → `Date` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public dates` → `Date` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public datetimes` → `Datetime` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public decimalValue` → `Decimal` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public decimals` → `Decimal` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public doubleValue` → `Double` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public doubles` → `Double` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public integerValue` → `Integer` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public integers` → `Integer` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public key` → `String` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public longValue` → `Long` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public longs` → `Long` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public sobjectValue` → `SObject` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public sobjects` → `SObject` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public stringValue` → `String` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +### `public strings` → `String` + +`AURAENABLED` +`INVOCABLEVARIABLE` + +--- + +## Methods + +### `private void determineTypeAndSetCastedValue(Object value)` + +`SUPPRESSWARNINGS` + +Method is responsible for determining the type of the value and setting the appropriate field. + +#### Parameters + +| Param | Description | +| ------- | ------------------------- | +| `value` | Object the Tuple's Value. | + +--- + +## Classes + +### TupleException + +A custom Exception type thrown when the incoming Object is not a recognized Apex-defined-type safe +type. + +**Inheritance** + +TupleException + +--- diff --git a/docs/home.md b/docs/home.md index 16f7c484..0a45fb65 100644 --- a/docs/home.md +++ b/docs/home.md @@ -349,6 +349,14 @@ inner class for managing the loop count per handler ### [TriggerFrameworkTests](https://github.com/codefriar/ApexKit/wiki/Miscellaneous/TriggerFrameworkTests) +### [Tuple](https://github.com/codefriar/ApexKit/wiki/Miscellaneous/Tuple) + +Tuple represents a key-value pair. Kinda. Don't come at me math nerds. +You may be asking why this exists, given the existence of Map. Unfortuately Map isn't available everywhere. +Notably, it's not available in Apex-defined Data Types used by Flow/Invocable actions. +Additionally, `Object` is not a v… + + ### [UFInvocable](https://github.com/codefriar/ApexKit/wiki/Miscellaneous/UFInvocable) This provides a common interface for classes & methods developers want to expose to flow. diff --git a/force-app/main/default/classes/dataStructures/Tuple.cls b/force-app/main/default/classes/dataStructures/Tuple.cls new file mode 100644 index 00000000..c3699264 --- /dev/null +++ b/force-app/main/default/classes/dataStructures/Tuple.cls @@ -0,0 +1,152 @@ +/** + * @description Tuple represents a key-value pair. Kinda. Don't come at me math nerds. + * + * You may be asking why this exists, given the existence of Map. Unfortuately Map isn't available everywhere. + * Notably, it's not available in Apex-defined Data Types used by Flow/Invocable actions. + * + * Additionally, `Object` is not a valid data type in Apex-defined Data Types, so we can't use a list of objects + * that have a string key, and Object value. This is the next best thing. A kind of polyfill for Map + * for use in Apex-defined Data Types. + * + * See also: https://help.salesforce.com/s/articleView?id=sf.flow_considerations_apex_data_type.htm&type=5 + * Available primitive datatypes available for use in tuple: + * Boolean, Integer, Long, Decimal, Double, Date, DateTime, and String. Single values and lists are supported for each data type. + */ +@SuppressWarnings('PMD.StdCyclomaticComplexity') +public with sharing class Tuple { + @AuraEnabled + @InvocableVariable + public String key; + + @AuraEnabled + @InvocableVariable + public Boolean[] booleans; + @AuraEnabled + @InvocableVariable + public Boolean booleanValue; + @AuraEnabled + @InvocableVariable + public Date dateValue; + @AuraEnabled + @InvocableVariable + public Date[] dates; + @AuraEnabled + @InvocableVariable + public Datetime[] datetimes; + @AuraEnabled + @InvocableVariable + public Datetime dateTimeValue; + @AuraEnabled + @InvocableVariable + public Double doubleValue; + @AuraEnabled + @InvocableVariable + public Double[] doubles; + @AuraEnabled + @InvocableVariable + public Decimal decimalValue; + @AuraEnabled + @InvocableVariable + public Decimal[] decimals; + @AuraEnabled + @InvocableVariable + public Integer integerValue; + @AuraEnabled + @InvocableVariable + public Integer[] integers; + @AuraEnabled + @InvocableVariable + public Long longValue; + @AuraEnabled + @InvocableVariable + public Long[] longs; + @AuraEnabled + @InvocableVariable + public String stringValue; + @AuraEnabled + @InvocableVariable + public String[] strings; + @AuraEnabled + @InvocableVariable + public SObject sobjectValue; + @AuraEnabled + @InvocableVariable + public SObject[] sobjects; + + /** + * @description In order to create a Tuple instance from within a flow, you need a no-arg constructor. + */ + @SuppressWarnings('PMD.EmptyStatementBlock') + public Tuple() { + } + + /** + * @description standard constructor accepting a key and value + * @param key String the name of the Tuple's Key. + * @param value Object the Tuple's Value. + */ + public Tuple(String key, Object value) { + if (key == null) { + throw new TupleException('Key cannot be null'); + } + if (value == null) { + throw new TupleException('Value cannot be null'); + } + this.key = key; + determineTypeAndSetCastedValue(value); + } + + /** + * @description Method is responsible for determining the type of the value and setting the appropriate field. + * @param value Object the Tuple's Value. + */ + @SuppressWarnings('PMD.CyclomaticComplexity, PMD.StdCyclomaticComplexity') + private void determineTypeAndSetCastedValue(Object value) { + if (value instanceof Boolean) { + this.booleanValue = (Boolean) value; + } else if (value instanceof List) { + this.booleans = (List) value; + } else if (value instanceof Datetime) { + this.dateTimeValue = (Datetime) value; + } else if (value instanceof List) { + this.datetimes = (List) value; + } else if (value instanceof Date) { + this.dateValue = (Date) value; + } else if (value instanceof List) { + this.dates = (List) value; + } else if (value instanceof Long) { + this.longValue = (Long) value; + } else if (value instanceof List) { + this.longs = (List) value; + } else if (value instanceof Integer) { + this.integerValue = (Integer) value; + } else if (value instanceof List) { + this.integers = (List) value; + } else if (value instanceof Decimal) { + this.decimalValue = (Decimal) value; + } else if (value instanceof List) { + this.decimals = (List) value; + } else if (value instanceof Double) { + this.doubleValue = (Double) value; + } else if (value instanceof List) { + this.doubles = (List) value; + } else if (value instanceof String) { + this.stringValue = (String) value; + } else if (value instanceof List) { + this.strings = (List) value; + } else if (value instanceof List) { + this.sobjects = (List) value; + } else if (value instanceof SObject) { + this.sobjectValue = (SObject) value; + } else { + throw new TupleException('Unsupported data type: ' + value); + } + } + + /** + * @description A custom Exception type thrown when the incoming Object is not a recognized Apex-defined-type safe + * type. + */ + public class TupleException extends Exception { + } +} diff --git a/force-app/main/default/classes/dataStructures/Tuple.cls-meta.xml b/force-app/main/default/classes/dataStructures/Tuple.cls-meta.xml new file mode 100644 index 00000000..7a518297 --- /dev/null +++ b/force-app/main/default/classes/dataStructures/Tuple.cls-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + Active + diff --git a/pmd/ruleset.xml b/pmd/ruleset.xml index 0ed5a9ab..53a2e24f 100644 --- a/pmd/ruleset.xml +++ b/pmd/ruleset.xml @@ -5,6 +5,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd"> Security Rules for Apex + .*/.sfdx/.* + .*/.sf/.* + node_modules