├── vercel.json ├── website ├── public │ ├── logo.png │ └── favicon.ico ├── installation.md ├── .vitepress │ └── config.mts ├── using-constants.md ├── creating-constants.md ├── best-practices.md ├── examples.md ├── getting-started.md ├── how-it-works.md └── index.md ├── force-app └── main │ └── default │ └── classes │ ├── Consts.cls-meta.xml │ ├── ConstsTest.cls-meta.xml │ ├── concrete-consts │ ├── AccountConsts.cls-meta.xml │ ├── ContactConsts.cls-meta.xml │ ├── ProfileConsts.cls-meta.xml │ ├── OpportunityConsts.cls-meta.xml │ ├── ContactConsts.cls │ ├── OpportunityConsts.cls │ ├── AccountConsts.cls │ └── ProfileConsts.cls │ ├── Consts.cls │ └── ConstsTest.cls ├── sfdx-project.json ├── config └── project-scratch-def.json ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── workflows │ └── ci.yml └── PULL_REQUEST_TEMPLATE.md ├── LICENSE ├── .gitignore ├── package.json ├── SECURITY.md ├── README.md ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "npm run docs:build", 3 | "outputDirectory": "website/.vitepress/dist" 4 | } 5 | -------------------------------------------------------------------------------- /website/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beyond-the-cloud-dev/apex-consts/HEAD/website/public/logo.png -------------------------------------------------------------------------------- /website/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beyond-the-cloud-dev/apex-consts/HEAD/website/public/favicon.ico -------------------------------------------------------------------------------- /force-app/main/default/classes/Consts.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/ConstsTest.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/concrete-consts/AccountConsts.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/concrete-consts/ContactConsts.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/concrete-consts/ProfileConsts.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/concrete-consts/OpportunityConsts.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /sfdx-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageDirectories": [ 3 | { 4 | "path": "force-app", 5 | "default": true 6 | } 7 | ], 8 | "name": "apex-consts", 9 | "namespace": "", 10 | "sfdcLoginUrl": "https://login.salesforce.com", 11 | "sourceApiVersion": "55.0" 12 | } 13 | -------------------------------------------------------------------------------- /config/project-scratch-def.json: -------------------------------------------------------------------------------- 1 | { 2 | "orgName": "Beyond The Cloud Dev", 3 | "edition": "Developer", 4 | "features": ["EnableSetPasswordInApi"], 5 | "settings": { 6 | "lightningExperienceSettings": { 7 | "enableS1DesktopEnabled": true 8 | }, 9 | "mobileSettings": { 10 | "enableS1EncryptedStoragePref2": false 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: enhancement 6 | # assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | ```java 16 | // code here 17 | ``` 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: bug 6 | # assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Apex script to reproduce the behavior: 14 | 15 | ```java 16 | // code here 17 | ``` 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /force-app/main/default/classes/concrete-consts/ContactConsts.cls: -------------------------------------------------------------------------------- 1 | @SuppressWarnings('PMD.FieldNamingConventions, PMD.EmptyStatementBlock') 2 | public class ContactConsts { 3 | public static final ContactConsts INSTANCE = new ContactConsts(); 4 | 5 | public final String API_NAME = Contact.sObjectType.getDescribe().getName(); 6 | 7 | public final Status STATUS = new Status(); 8 | 9 | public class Status { 10 | public final String IN_APPROVAL_PROCESS = 'In Approval Process'; 11 | public final String ACTIVATED = 'Activated'; 12 | public final String DRAFT = 'Draft'; 13 | } 14 | 15 | private ContactConsts() {} 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | workflow_dispatch: 9 | 10 | jobs: 11 | salesforce-ci: 12 | uses: beyond-the-cloud-dev/cicd-template/.github/workflows/salesforce-ci.yml@main 13 | with: 14 | node-version: "20" 15 | sf-cli-version: "latest" 16 | scratch-org-duration: 1 17 | test-level: "RunLocalTests" 18 | upload-to-codecov: true 19 | codecov-slug: ${{ github.repository }} # Automatically uses current repository 20 | secrets: 21 | SFDX_AUTH_URL_DEVHUB: ${{ secrets.SFDX_AUTH_URL_DEVHUB }} 22 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 23 | -------------------------------------------------------------------------------- /force-app/main/default/classes/Consts.cls: -------------------------------------------------------------------------------- 1 | @SuppressWarnings('PMD.PropertyNamingConventions') 2 | public class Consts { 3 | public static final AccountConsts ACCOUNT { 4 | get { 5 | return AccountConsts.INSTANCE; 6 | } 7 | } 8 | 9 | public static final ContactConsts CONTACT { 10 | get { 11 | return ContactConsts.INSTANCE; 12 | } 13 | } 14 | 15 | public static final OpportunityConsts OPPORTUNITY { 16 | get { 17 | return OpportunityConsts.INSTANCE; 18 | } 19 | } 20 | 21 | public static final ProfileConsts PROFILE { 22 | get { 23 | return ProfileConsts.INSTANCE; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /force-app/main/default/classes/ConstsTest.cls: -------------------------------------------------------------------------------- 1 | @IsTest 2 | private class ConstsTest { 3 | @IsTest 4 | static void accountConsts() { 5 | Assert.isNotNull(Consts.ACCOUNT, 'Account constants should not be null'); 6 | } 7 | 8 | @IsTest 9 | static void contactConsts() { 10 | Assert.isNotNull(Consts.CONTACT, 'Contact constants should not be null'); 11 | } 12 | 13 | @IsTest 14 | static void opportunityConsts() { 15 | Assert.isNotNull(Consts.OPPORTUNITY, 'Opportunity constants should not be null'); 16 | } 17 | 18 | @IsTest 19 | static void profileConsts() { 20 | Assert.isNotNull(Consts.PROFILE, 'Profile constants should not be null'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /force-app/main/default/classes/concrete-consts/OpportunityConsts.cls: -------------------------------------------------------------------------------- 1 | @SuppressWarnings('PMD.FieldNamingConventions, PMD.EmptyStatementBlock') 2 | public class OpportunityConsts { 3 | public static final OpportunityConsts INSTANCE = new OpportunityConsts(); 4 | 5 | public final String API_NAME = Opportunity.sObjectType.getDescribe().getName(); 6 | 7 | public final Type TYPE = new Type(); 8 | 9 | public class Type { 10 | public final String CHANNEL_PARTNER_RESELLER = 'Channel Partner / Reseller'; 11 | public final String EXISTING_CUSTOMER_DOWNGRADE = 'Existing Customer - Downgrade'; 12 | public final String EXISTING_CUSTOMER_REPLACEMENT = 'Existing Customer - Replacement'; 13 | public final String EXISTING_CUSTOMER_UPGRADE = 'Existing Customer - Upgrade'; 14 | public final String NEW_CUSTOMER = 'New Customer'; 15 | } 16 | 17 | private OpportunityConsts() {} 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Beyond The Cloud Dev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /force-app/main/default/classes/concrete-consts/AccountConsts.cls: -------------------------------------------------------------------------------- 1 | @SuppressWarnings('PMD.FieldNamingConventions, PMD.EmptyStatementBlock') 2 | public class AccountConsts { 3 | public static final AccountConsts INSTANCE = new AccountConsts(); 4 | 5 | public final String API_NAME = Account.sObjectType.getDescribe().getName(); 6 | 7 | public final Type TYPE = new Type(); 8 | public final Rating RATING = new Rating(); 9 | 10 | public class Type { 11 | public final String CHANNEL_PARTNER_RESELLER = 'Channel Partner / Reseller'; 12 | public final String CUSTOMER_CHANNEL = 'Customer - Channel'; 13 | public final String CUSTOMER_DIRECT = 'Customer - Direct'; 14 | public final String INSTALLATION_PARTNER = 'Installation Partner'; 15 | public final String OTHER = 'Other'; 16 | public final String PROSPECT = 'Prospect'; 17 | public final String TECHNOLOGY_PARTNER = 'Technology Partner'; 18 | } 19 | 20 | public class Rating { 21 | public final String COLD = 'Cold'; 22 | public final String HOT = 'Hot'; 23 | public final String WARM = 'Warm'; 24 | } 25 | 26 | private AccountConsts() {} 27 | } 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used for Git repositories to specify intentionally untracked files that Git should ignore. 2 | # If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore 3 | # For useful gitignore templates see: https://github.com/github/gitignore 4 | 5 | # IDE 6 | .idea/ 7 | .project/ 8 | .nx-cache 9 | .vscode/ 10 | .prettierrc 11 | 12 | # Salesforce cache 13 | .sf/ 14 | .sfdx/ 15 | .localdevserver/ 16 | deploy-options.json 17 | 18 | # CumulusCI 19 | .cci/ 20 | 21 | # LWC VSCode autocomplete 22 | **/lwc/jsconfig.json 23 | 24 | # LWC Jest coverage reports 25 | coverage/ 26 | 27 | # Logs 28 | logs 29 | *.log 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | -local-* 34 | 35 | # Dependency directories 36 | node_modules/ 37 | 38 | # Eslint cache 39 | .eslintcache 40 | 41 | # MacOS system files 42 | .DS_Store 43 | 44 | # Windows system files 45 | Thumbs.db 46 | ehthumbs.db 47 | [Dd]esktop.ini 48 | $RECYCLE.BIN/ 49 | 50 | # Local environment variables 51 | .env 52 | 53 | # SOQL Query Results 54 | **/scripts/soql/query-results 55 | 56 | #Private keys 57 | *.key 58 | 59 | # VitePress cache 60 | website/.vitepress/cache/ 61 | website/.vitepress/dist/ 62 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "salesforce-repo", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "Salesforce Repo", 6 | "scripts": { 7 | "lint": "eslint **/{aura,lwc}/**", 8 | "test": "npm run test:unit", 9 | "test:unit": "sfdx-lwc-jest", 10 | "test:unit:watch": "sfdx-lwc-jest --watch", 11 | "test:unit:debug": "sfdx-lwc-jest --debug", 12 | "test:unit:coverage": "sfdx-lwc-jest --coverage", 13 | "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", 14 | "prettier:verify": "prettier --list-different \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", 15 | "prepare": "husky", 16 | "precommit": "lint-staged", 17 | "docs:dev": "vitepress dev website", 18 | "docs:build": "vitepress build website", 19 | "docs:preview": "vitepress preview website" 20 | }, 21 | "devDependencies": { 22 | "@lwc/eslint-plugin-lwc": "^3.3.0", 23 | "@prettier/plugin-xml": "^3.4.2", 24 | "@salesforce/eslint-config-lwc": "^4.1.2", 25 | "@salesforce/eslint-plugin-aura": "^3.0.0", 26 | "@salesforce/eslint-plugin-lightning": "^2.0.0", 27 | "@salesforce/sfdx-lwc-jest": "^7.1.2", 28 | "eslint": "^9.39.2", 29 | "eslint-plugin-import": "^2.32.0", 30 | "eslint-plugin-jest": "^29.5.0", 31 | "husky": "^9.1.7", 32 | "lint-staged": "^16.2.7", 33 | "prettier": "^3.7.4", 34 | "prettier-plugin-apex": "^2.2.6", 35 | "vitepress": "^1.6.4", 36 | "vue": "^3.5.26" 37 | }, 38 | "lint-staged": { 39 | "**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}": [ 40 | "prettier --write" 41 | ], 42 | "**/{aura,lwc}/**": [ 43 | "eslint" 44 | ], 45 | "website/**/*.{js,ts,vue,mts}": [ 46 | "prettier --write" 47 | ], 48 | "website/**/*.md": [ 49 | "prettier --write" 50 | ] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | ## Type of Change 6 | 7 | 8 | 9 | - [ ] Bug fix (non-breaking change which fixes an issue) 10 | - [ ] New feature (non-breaking change which adds functionality) 11 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 12 | - [ ] Documentation update 13 | - [ ] Code refactoring 14 | - [ ] Test improvements 15 | - [ ] CI/CD improvements 16 | 17 | ## Changes Made 18 | 19 | 20 | 21 | - 22 | - 23 | - 24 | 25 | ## Related Issues 26 | 27 | 28 | 29 | Fixes # 30 | Closes # 31 | 32 | ## Testing 33 | 34 | 35 | 36 | - [ ] All existing tests pass (`npm test`) 37 | - [ ] Added new tests for new functionality 38 | - [ ] Tested in scratch org 39 | - [ ] Linting passes (`npm run lint`) 40 | - [ ] Code formatting is correct (`npm run prettier:verify`) 41 | 42 | ## Screenshots 43 | 44 | 45 | 46 | ## Checklist 47 | 48 | 49 | 50 | - [ ] My code follows the style guidelines of this project 51 | - [ ] I have performed a self-review of my own code 52 | - [ ] I have commented my code where necessary 53 | - [ ] I have made corresponding changes to the documentation 54 | - [ ] My changes generate no new warnings or errors 55 | - [ ] I have added tests that prove my fix is effective or that my feature works 56 | - [ ] New and existing unit tests pass locally with my changes 57 | - [ ] Any dependent changes have been merged and published 58 | 59 | ## Additional Notes 60 | 61 | 62 | -------------------------------------------------------------------------------- /website/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | Install Apex Consts in your Salesforce org. 4 | 5 | ## Using Salesforce CLI 6 | 7 | ### Deploy Source Code 8 | 9 | ```bash 10 | # Clone the repository 11 | git clone https://github.com/beyond-the-cloud-dev/apex-consts.git 12 | cd apex-consts 13 | 14 | # Deploy to your org 15 | sf project deploy start --target-org your-org-alias 16 | ``` 17 | 18 | ## Manual Installation 19 | 20 | ### Using Setup UI 21 | 22 | 1. Navigate to **Setup** → **Apex Classes** 23 | 2. Click **New** 24 | 3. Copy the code from: 25 | - [Consts.cls](https://github.com/beyond-the-cloud-dev/apex-consts/blob/main/force-app/main/default/classes/Consts.cls) 26 | - [AccountConsts.cls](https://github.com/beyond-the-cloud-dev/apex-consts/blob/main/force-app/main/default/classes/concrete-consts/AccountConsts.cls) 27 | - [ContactConsts.cls](https://github.com/beyond-the-cloud-dev/apex-consts/blob/main/force-app/main/default/classes/concrete-consts/ContactConsts.cls) 28 | - [OpportunityConsts.cls](https://github.com/beyond-the-cloud-dev/apex-consts/blob/main/force-app/main/default/classes/concrete-consts/OpportunityConsts.cls) 29 | - [ProfileConsts.cls](https://github.com/beyond-the-cloud-dev/apex-consts/blob/main/force-app/main/default/classes/concrete-consts/ProfileConsts.cls) 30 | 4. Save each class 31 | 32 | ## Dependencies 33 | 34 | Apex Consts has **zero dependencies**. It works standalone. 35 | 36 | ## API Version 37 | 38 | Requires Salesforce API version **64.0** or higher. 39 | 40 | ## Verification 41 | 42 | Test the installation: 43 | 44 | ```apex 45 | System.debug(Consts.ACCOUNT.TYPE.PROSPECT); // 'Prospect' 46 | System.debug(Consts.ACCOUNT.API_NAME); // 'Account' 47 | ``` 48 | 49 | If these work, you're all set! ✅ 50 | 51 | ## Next Steps 52 | 53 | - [Getting Started Guide](/getting-started) 54 | - [See Examples](/examples) 55 | - [Create Custom Constants](/creating-constants) 56 | -------------------------------------------------------------------------------- /website/.vitepress/config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitepress' 2 | 3 | export default defineConfig({ 4 | title: "Apex Consts", 5 | description: "A structured framework for managing constants in Salesforce Apex", 6 | base: '/', 7 | themeConfig: { 8 | logo: '/logo.png', 9 | 10 | nav: [ 11 | { text: 'Home', link: '/' }, 12 | { text: 'Guide', link: '/getting-started' }, 13 | { text: 'Examples', link: '/examples' } 14 | ], 15 | 16 | sidebar: [ 17 | { 18 | text: 'Introduction', 19 | items: [ 20 | { text: 'Getting Started', link: '/getting-started' }, 21 | { text: 'Installation', link: '/installation' }, 22 | { text: 'How It Works', link: '/how-it-works' } 23 | ] 24 | }, 25 | { 26 | text: 'Usage', 27 | items: [ 28 | { text: 'Using Constants', link: '/using-constants' }, 29 | { text: 'Creating Custom Constants', link: '/creating-constants' }, 30 | { text: 'Best Practices', link: '/best-practices' } 31 | ] 32 | }, 33 | { 34 | text: 'Built-in Constants', 35 | items: [ 36 | { text: 'Account', link: '/constants/account' }, 37 | { text: 'Contact', link: '/constants/contact' }, 38 | { text: 'Opportunity', link: '/constants/opportunity' }, 39 | { text: 'Profile', link: '/constants/profile' } 40 | ] 41 | }, 42 | { 43 | text: 'Examples', 44 | items: [ 45 | { text: 'Basic Examples', link: '/examples' } 46 | ] 47 | } 48 | ], 49 | 50 | socialLinks: [ 51 | { icon: 'github', link: 'https://github.com/beyond-the-cloud-dev/apex-consts' } 52 | ], 53 | 54 | footer: { 55 | message: 'Part of Apex Fluently', 56 | copyright: 'Copyright © 2024 Beyond the Cloud' 57 | }, 58 | 59 | search: { 60 | provider: 'local' 61 | } 62 | } 63 | }) 64 | -------------------------------------------------------------------------------- /website/using-constants.md: -------------------------------------------------------------------------------- 1 | # Using Constants 2 | 3 | Learn how to use Apex Consts in your code. 4 | 5 | ## Basic Usage 6 | 7 | Access constants using the `Consts` class: 8 | 9 | ```apex 10 | // Account Type 11 | String type = Consts.ACCOUNT.TYPE.PROSPECT; 12 | 13 | // Account Rating 14 | String rating = Consts.ACCOUNT.RATING.HOT; 15 | 16 | // API Name 17 | String apiName = Consts.ACCOUNT.API_NAME; 18 | ``` 19 | 20 | ## Creating Records 21 | 22 | ```apex 23 | Account acc = new Account( 24 | Name = 'Acme Corp', 25 | Type = Consts.ACCOUNT.TYPE.PROSPECT, 26 | Rating = Consts.ACCOUNT.RATING.HOT 27 | ); 28 | insert acc; 29 | ``` 30 | 31 | ## SOQL Queries 32 | 33 | ```apex 34 | List hotProspects = [ 35 | SELECT Id, Name 36 | FROM Account 37 | WHERE Type = :Consts.ACCOUNT.TYPE.PROSPECT 38 | AND Rating = :Consts.ACCOUNT.RATING.HOT 39 | ]; 40 | ``` 41 | 42 | ## Conditional Logic 43 | 44 | ```apex 45 | if (account.Type == Consts.ACCOUNT.TYPE.PROSPECT) { 46 | // Prospect logic 47 | } else if (account.Type == Consts.ACCOUNT.TYPE.CUSTOMER_DIRECT) { 48 | // Customer logic 49 | } 50 | ``` 51 | 52 | ## Switch Statements 53 | 54 | ```apex 55 | switch on account.Rating { 56 | when 'Hot' { 57 | // Use constants for comparison 58 | if (account.Rating == Consts.ACCOUNT.RATING.HOT) { 59 | // Hot account logic 60 | } 61 | } 62 | when 'Warm' { 63 | // Warm account logic 64 | } 65 | } 66 | ``` 67 | 68 | ## Updating Records 69 | 70 | ```apex 71 | Account acc = [SELECT Id, Type FROM Account WHERE Id = :accountId]; 72 | acc.Type = Consts.ACCOUNT.TYPE.CUSTOMER_DIRECT; 73 | acc.Rating = Consts.ACCOUNT.RATING.HOT; 74 | update acc; 75 | ``` 76 | 77 | ## Best Practices 78 | 79 | 1. **Always use constants** instead of hard-coded strings 80 | 2. **Import at class level** if using extensively 81 | 3. **Use in validation rules** via formulas when possible 82 | 4. **Document** when you deviate from constants 83 | 84 | [Next: Creating Custom Constants →](/creating-constants) 85 | -------------------------------------------------------------------------------- /website/creating-constants.md: -------------------------------------------------------------------------------- 1 | # Creating Custom Constants 2 | 3 | Extend Apex Consts with your own constant classes. 4 | 5 | ## Step 1: Create a Const Class 6 | 7 | Create a new class for your object: 8 | 9 | ```apex 10 | public class CustomObjectConsts { 11 | public static final CustomObjectConsts INSTANCE = new CustomObjectConsts(); 12 | 13 | public final String API_NAME = CustomObject__c.sObjectType.getDescribe().getName(); 14 | 15 | public final Status STATUS = new Status(); 16 | public final Type TYPE = new Type(); 17 | 18 | public class Status { 19 | public final String DRAFT = 'Draft'; 20 | public final String ACTIVE = 'Active'; 21 | public final String ARCHIVED = 'Archived'; 22 | } 23 | 24 | public class Type { 25 | public final String TYPE_A = 'Type A'; 26 | public final String TYPE_B = 'Type B'; 27 | } 28 | 29 | private CustomObjectConsts() {} 30 | } 31 | ``` 32 | 33 | ## Step 2: Add to Consts Class 34 | 35 | Register your class in `Consts.cls`: 36 | 37 | ```apex 38 | public class Consts { 39 | // ... existing constants ... 40 | 41 | public static final CustomObjectConsts CUSTOM_OBJECT { 42 | get { 43 | return CustomObjectConsts.INSTANCE; 44 | } 45 | } 46 | } 47 | ``` 48 | 49 | ## Step 3: Use Your Constants 50 | 51 | ```apex 52 | CustomObject__c obj = new CustomObject__c( 53 | Name = 'Test', 54 | Status__c = Consts.CUSTOM_OBJECT.STATUS.DRAFT, 55 | Type__c = Consts.CUSTOM_OBJECT.TYPE.TYPE_A 56 | ); 57 | insert obj; 58 | ``` 59 | 60 | ## Template 61 | 62 | Copy this template for new const classes: 63 | 64 | ```apex 65 | public class YourObjectConsts { 66 | public static final YourObjectConsts INSTANCE = new YourObjectConsts(); 67 | 68 | public final String API_NAME = YourObject__c.sObjectType.getDescribe().getName(); 69 | 70 | // Add your inner classes here 71 | public final YourFieldGroup YOUR_FIELD_GROUP = new YourFieldGroup(); 72 | 73 | public class YourFieldGroup { 74 | public final String VALUE_1 = 'Value 1'; 75 | public final String VALUE_2 = 'Value 2'; 76 | } 77 | 78 | private YourObjectConsts() {} 79 | } 80 | ``` 81 | 82 | [View Examples →](/examples) 83 | -------------------------------------------------------------------------------- /website/best-practices.md: -------------------------------------------------------------------------------- 1 | # Best Practices 2 | 3 | Guidelines for using Apex Consts effectively. 4 | 5 | ## Do's ✅ 6 | 7 | ### Use Constants Everywhere 8 | 9 | Replace all hard-coded strings with constants: 10 | 11 | ```apex 12 | // ✅ Good 13 | acc.Type = Consts.ACCOUNT.TYPE.PROSPECT; 14 | 15 | // ❌ Bad 16 | acc.Type = 'Prospect'; 17 | ``` 18 | 19 | ### Group Related Constants 20 | 21 | Use inner classes to organize related values: 22 | 23 | ```apex 24 | public class CustomConsts { 25 | public final Status STATUS = new Status(); 26 | public final Priority PRIORITY = new Priority(); 27 | 28 | public class Status { 29 | public final String OPEN = 'Open'; 30 | public final String CLOSED = 'Closed'; 31 | } 32 | 33 | public class Priority { 34 | public final String HIGH = 'High'; 35 | public final String LOW = 'Low'; 36 | } 37 | } 38 | ``` 39 | 40 | ### Keep Values Synchronized 41 | 42 | Update constants when picklist values change in Salesforce. 43 | 44 | ## Don'ts ❌ 45 | 46 | ### Don't Instantiate Directly 47 | 48 | ```apex 49 | // ❌ Never do this 50 | AccountConsts consts = new AccountConsts(); 51 | 52 | // ✅ Always use Consts 53 | String type = Consts.ACCOUNT.TYPE.PROSPECT; 54 | ``` 55 | 56 | ### Don't Cache in Variables 57 | 58 | No need to cache - the framework handles efficiency: 59 | 60 | ```apex 61 | // ❌ Unnecessary 62 | final String prospectType = Consts.ACCOUNT.TYPE.PROSPECT; 63 | if (acc.Type == prospectType) { } 64 | 65 | // ✅ Just use directly 66 | if (acc.Type == Consts.ACCOUNT.TYPE.PROSPECT) { } 67 | ``` 68 | 69 | ### Don't Mix Approaches 70 | 71 | ```apex 72 | // ❌ Inconsistent 73 | acc.Type = Consts.ACCOUNT.TYPE.PROSPECT; 74 | acc.Rating = 'Hot'; // Should use constant 75 | 76 | // ✅ Consistent 77 | acc.Type = Consts.ACCOUNT.TYPE.PROSPECT; 78 | acc.Rating = Consts.ACCOUNT.RATING.HOT; 79 | ``` 80 | 81 | ## Performance Tips 82 | 83 | 1. **No Performance Penalty** - Constants access is extremely fast 84 | 2. **Memory Efficient** - Singleton pattern minimizes heap usage 85 | 3. **Use in Loops** - Safe to use in bulk operations 86 | 87 | ## Maintenance 88 | 89 | 1. **Document Custom Constants** - Add comments explaining business logic 90 | 2. **Version Control** - Track changes to constants 91 | 3. **Review Regularly** - Ensure constants match Salesforce metadata 92 | 4. **Update Tests** - Keep test data using constants 93 | 94 | [See Examples →](/examples) 95 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | This template is actively maintained and we recommend always using the latest version. 6 | 7 | | Version | Supported | 8 | | -------- | ------------------ | 9 | | Latest | :white_check_mark: | 10 | | < Latest | :x: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | If you discover a security vulnerability in this Salesforce template, please report it responsibly. 15 | 16 | ### How to Report 17 | 18 | **DO NOT** create a public GitHub issue for security vulnerabilities. 19 | 20 | Instead, please report security issues via email to: 21 | 22 | 📧 **contact@beyondthecloud.dev** 23 | 24 | ### What to Include 25 | 26 | When reporting a vulnerability, please include: 27 | 28 | - Description of the vulnerability 29 | - Steps to reproduce the issue 30 | - Potential impact 31 | - Suggested fix (if you have one) 32 | - Your contact information 33 | 34 | ### Response Timeline 35 | 36 | - We will acknowledge receipt of your vulnerability report within **3 business days** 37 | - We will provide a more detailed response within **7 business days** 38 | - We will work with you to understand and address the issue 39 | - We will notify you when the vulnerability has been fixed 40 | 41 | ### Responsible Disclosure 42 | 43 | We appreciate responsible disclosure and will: 44 | 45 | - Keep you informed about our progress 46 | - Credit you in the fix (if you wish) 47 | - Work to address the issue as quickly as possible 48 | 49 | ## Security Best Practices 50 | 51 | When using this template: 52 | 53 | ### Salesforce Security 54 | 55 | - **Never commit credentials** - Use `.gitignore` for sensitive files 56 | - **Use scratch org URLs** - Rotate Dev Hub auth URLs regularly 57 | - **Review permissions** - Implement proper sharing and FLS checks 58 | - **Validate input** - Prevent SOQL injection and XSS 59 | - **Use secrets management** - Store GitHub secrets securely 60 | 61 | ### Code Quality 62 | 63 | - Run security checks: `npm run lint` 64 | - Review dependencies: `npm audit` 65 | - Keep dependencies updated: `npm update` 66 | - Use pre-commit hooks (Husky) 67 | 68 | ### CI/CD Security 69 | 70 | - **Protect GitHub secrets** - Limit access to `SFDX_AUTH_URL_DEVHUB` 71 | - **Branch protection** - Enable branch protection on `main` 72 | - **Review workflows** - Audit GitHub Actions regularly 73 | - **Limit permissions** - Use minimal required permissions 74 | 75 | ## Security Resources 76 | 77 | - [Salesforce Security Guide](https://developer.salesforce.com/docs/atlas.en-us.secure_coding_guide.meta/secure_coding_guide/) 78 | - [OWASP Top 10](https://owasp.org/www-project-top-ten/) 79 | - [GitHub Security Best Practices](https://docs.github.com/en/code-security) 80 | 81 | ## Contact 82 | 83 | For security concerns, contact: 84 | 85 | **Beyond The Cloud Sp. z o.o.** 86 | 87 | - Email: contact@beyondthecloud.dev 88 | - Website: [beyondthecloud.dev](https://beyondthecloud.dev) 89 | 90 | --- 91 | 92 | Thank you for helping keep this template and its users safe! 🔒 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | Apex Consts logo 6 | 7 | 8 |

Apex Consts

9 | 10 | Beyond The Cloud logo 11 | API version 12 | License 13 | 14 |
15 | 16 | The Constants Framework provides a structured approach for managing constants in the Apex. 17 | 18 | Consts Lib is part of [Apex Fluently](https://apexfluently.beyondthecloud.dev/), a suite of production-ready Salesforce libraries by Beyond the Cloud. 19 | 20 | ## Example 21 | 22 | ```java 23 | Account acc = new Account( 24 | Name = 'My Account', 25 | Type = Consts.ACCOUNT.TYPE.PROSPECT, 26 | Rating = Consts.ACCOUNT.RATING.HOT 27 | ); 28 | ``` 29 | 30 | ```java 31 | System.debug(Consts.ACCOUNT.TYPE.PROSPECT); //'Prospect' 32 | System.debug(Consts.ACCOUNT.RATING.HOT); //'Hit' 33 | 34 | System.debug(Consts.CONTACT.API_NAME); //'Contact' 35 | System.debug(Consts.CONTACT.LEAD_SOURCE.WEB); //'Web' 36 | 37 | System.debug(Consts.OPPORTUNITY.TYPE.EXISTING_CUSTOMER_DOWNGRADE); //'Existing Customer - Downgrade' 38 | ``` 39 | 40 | ## How it works? 41 | 42 | The framework employs the concept of singletons to create concrete classes. 43 | Each class is initialized once during the transaction, reducing heap size usage. 44 | 45 | Getters and setters are used to lazily initialize the classes. 46 | For example, accessing `Consts.Account.TYPE.PROSPECT` will only create an instance of the `AccountConsts` class without creating `ContactConsts`. 47 | 48 | The code architecture follows the Open/Closed and Single Responsibility Principle principles. 49 | This design ensures the code is easily extensible, and each class is responsible for a specific set of constants. 50 | 51 | ## How to use it? 52 | 53 | ### Create a concrete consts class 54 | 55 | - Define an `INSTANCE` variable to hold the class instance (singleton). 56 | - Create inner classes to organize the constant values. 57 | 58 | ```java 59 | public class ContactConsts { 60 | public static final ContactConsts INSTANCE = new ContactConsts(); 61 | 62 | public final String API_NAME = Contact.sObjectType.getDescribe().getName(); 63 | 64 | public final Status STATUS = new Status(); 65 | 66 | public class Status { 67 | public final String IN_APPROVAL_PROCESS = 'In Approval Process'; 68 | public final String ACTIVATED = 'Activated'; 69 | public final String DRAFT = 'Draft'; 70 | } 71 | } 72 | ``` 73 | 74 | ### Add a concrete consts class to `Consts` 75 | 76 | ```java 77 | public class Consts { 78 | 79 | public static final ContactConsts CONTACT { 80 | get { 81 | return ContactConsts.INSTANCE; 82 | } 83 | } 84 | } 85 | ``` 86 | -------------------------------------------------------------------------------- /website/examples.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Practical examples using Apex Consts. 4 | 5 | ## Basic Record Creation 6 | 7 | ```apex 8 | Account acc = new Account( 9 | Name = 'Acme Corp', 10 | Type = Consts.ACCOUNT.TYPE.PROSPECT, 11 | Rating = Consts.ACCOUNT.RATING.HOT 12 | ); 13 | insert acc; 14 | ``` 15 | 16 | ## SOQL with Constants 17 | 18 | ```apex 19 | List newCustomerOpps = [ 20 | SELECT Id, Name, Amount 21 | FROM Opportunity 22 | WHERE Type = :Consts.OPPORTUNITY.TYPE.NEW_CUSTOMER 23 | AND StageName = :Consts.OPPORTUNITY.STAGE_NAME.PROSPECTING 24 | ]; 25 | ``` 26 | 27 | ## Trigger Logic 28 | 29 | ```apex 30 | trigger AccountTrigger on Account (before insert, before update) { 31 | for (Account acc : Trigger.new) { 32 | if (acc.Type == Consts.ACCOUNT.TYPE.PROSPECT) { 33 | acc.Rating = Consts.ACCOUNT.RATING.WARM; 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | ## Batch Apex 40 | 41 | ```apex 42 | public class AccountBatch implements Database.Batchable { 43 | public Database.QueryLocator start(Database.BatchableContext bc) { 44 | return Database.getQueryLocator([ 45 | SELECT Id, Name, Type 46 | FROM Account 47 | WHERE Type = :Consts.ACCOUNT.TYPE.PROSPECT 48 | ]); 49 | } 50 | 51 | public void execute(Database.BatchableContext bc, List scope) { 52 | for (Account acc : scope) { 53 | acc.Type = Consts.ACCOUNT.TYPE.CUSTOMER_DIRECT; 54 | } 55 | update scope; 56 | } 57 | 58 | public void finish(Database.BatchableContext bc) {} 59 | } 60 | ``` 61 | 62 | ## Service Layer 63 | 64 | ```apex 65 | public class AccountService { 66 | public static void convertProspectToCustomer(Id accountId) { 67 | Account acc = [SELECT Id, Type FROM Account WHERE Id = :accountId]; 68 | 69 | if (acc.Type != Consts.ACCOUNT.TYPE.PROSPECT) { 70 | throw new IllegalArgumentException('Account is not a prospect'); 71 | } 72 | 73 | acc.Type = Consts.ACCOUNT.TYPE.CUSTOMER_DIRECT; 74 | acc.Rating = Consts.ACCOUNT.RATING.HOT; 75 | update acc; 76 | } 77 | } 78 | ``` 79 | 80 | ## Test Classes 81 | 82 | ```apex 83 | @IsTest 84 | private class AccountServiceTest { 85 | @IsTest 86 | static void testConvertProspect() { 87 | Account acc = new Account( 88 | Name = 'Test', 89 | Type = Consts.ACCOUNT.TYPE.PROSPECT 90 | ); 91 | insert acc; 92 | 93 | Test.startTest(); 94 | AccountService.convertProspectToCustomer(acc.Id); 95 | Test.stopTest(); 96 | 97 | acc = [SELECT Type, Rating FROM Account WHERE Id = :acc.Id]; 98 | Assert.areEqual(Consts.ACCOUNT.TYPE.CUSTOMER_DIRECT, acc.Type); 99 | Assert.areEqual(Consts.ACCOUNT.RATING.HOT, acc.Rating); 100 | } 101 | } 102 | ``` 103 | 104 | ## Dynamic SOQL 105 | 106 | ```apex 107 | public List getAccountsByType(String accountType) { 108 | String query = 'SELECT Id, Name FROM Account WHERE Type = :accountType'; 109 | return Database.query(query); 110 | } 111 | 112 | // Usage 113 | List prospects = getAccountsByType(Consts.ACCOUNT.TYPE.PROSPECT); 114 | ``` 115 | 116 | [Learn More →](/getting-started) 117 | -------------------------------------------------------------------------------- /website/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | Learn how to use Apex Consts to manage constants in your Salesforce org. 4 | 5 | ## What is Apex Consts? 6 | 7 | Apex Consts is a framework for managing constants in Salesforce Apex. Instead of hard-coding string literals throughout your code, you use centralized, type-safe constants that provide: 8 | 9 | - **Compile-time safety** - Catch typos before deployment 10 | - **IDE autocomplete** - Never remember exact picklist values 11 | - **Centralized management** - One place to update constants 12 | - **Better readability** - Self-documenting code 13 | 14 | ## Quick Start 15 | 16 | ### 1. Install the Library 17 | 18 | See the [Installation Guide](/installation) for setup instructions. 19 | 20 | ### 2. Use Built-in Constants 21 | 22 | Apex Consts comes with pre-built constants for standard Salesforce objects: 23 | 24 | ```apex 25 | // Account constants 26 | Account acc = new Account( 27 | Name = 'Acme Corp', 28 | Type = Consts.ACCOUNT.TYPE.PROSPECT, 29 | Rating = Consts.ACCOUNT.RATING.HOT 30 | ); 31 | 32 | // Contact constants 33 | Contact con = new Contact( 34 | FirstName = 'John', 35 | LastName = 'Doe', 36 | LeadSource = Consts.CONTACT.LEAD_SOURCE.WEB 37 | ); 38 | 39 | // Opportunity constants 40 | Opportunity opp = new Opportunity( 41 | Name = 'Big Deal', 42 | StageName = Consts.OPPORTUNITY.STAGE_NAME.PROSPECTING, 43 | Type = Consts.OPPORTUNITY.TYPE.NEW_CUSTOMER, 44 | CloseDate = Date.today().addDays(30) 45 | ); 46 | ``` 47 | 48 | ### 3. Access API Names 49 | 50 | Get sObject API names: 51 | 52 | ```apex 53 | String accountApiName = Consts.ACCOUNT.API_NAME; // 'Account' 54 | String contactApiName = Consts.CONTACT.API_NAME; // 'Contact' 55 | ``` 56 | 57 | ## Common Patterns 58 | 59 | ### Creating Records 60 | 61 | ```apex 62 | Account acc = new Account(); 63 | acc.Name = 'Acme Corp'; 64 | acc.Type = Consts.ACCOUNT.TYPE.CUSTOMER_DIRECT; 65 | acc.Rating = Consts.ACCOUNT.RATING.WARM; 66 | insert acc; 67 | ``` 68 | 69 | ### Query Filters 70 | 71 | ```apex 72 | List prospects = [ 73 | SELECT Id, Name 74 | FROM Account 75 | WHERE Type = :Consts.ACCOUNT.TYPE.PROSPECT 76 | AND Rating = :Consts.ACCOUNT.RATING.HOT 77 | ]; 78 | ``` 79 | 80 | ### Conditional Logic 81 | 82 | ```apex 83 | if (account.Type == Consts.ACCOUNT.TYPE.PROSPECT) { 84 | // Handle prospect logic 85 | } else if (account.Type == Consts.ACCOUNT.TYPE.CUSTOMER_DIRECT) { 86 | // Handle customer logic 87 | } 88 | ``` 89 | 90 | ## Why Use Constants? 91 | 92 | ### Without Apex Consts ❌ 93 | 94 | ```apex 95 | Account acc = new Account( 96 | Type = 'Propsect' // Typo! No compile error, but wrong value 97 | ); 98 | 99 | if (acc.Type == 'prospect') { // Wrong case, comparison fails 100 | // This never executes 101 | } 102 | ``` 103 | 104 | ### With Apex Consts ✅ 105 | 106 | ```apex 107 | Account acc = new Account( 108 | Type = Consts.ACCOUNT.TYPE.PROSPECT // Type-safe, autocomplete 109 | ); 110 | 111 | if (acc.Type == Consts.ACCOUNT.TYPE.PROSPECT) { // Works correctly 112 | // This executes as expected 113 | } 114 | ``` 115 | 116 | ## Next Steps 117 | 118 | - Learn [How It Works](/how-it-works) 119 | - See [More Examples](/examples) 120 | - [Create Your Own Constants](/creating-constants) 121 | -------------------------------------------------------------------------------- /force-app/main/default/classes/concrete-consts/ProfileConsts.cls: -------------------------------------------------------------------------------- 1 | @SuppressWarnings('PMD.FieldNamingConventions, PMD.EmptyStatementBlock, PMD.ExcessivePublicCount, PMD.TooManyFields') 2 | public class ProfileConsts { 3 | public static final ProfileConsts INSTANCE = new ProfileConsts(); 4 | 5 | public final Name NAME = new Name(); 6 | 7 | public class Name { 8 | public final String ANALYTICS_CLOUD_INTEGRATION_USER = 'Analytics Cloud Integration User'; 9 | public final String ANALYTICS_CLOUD_SECURITY_USER = 'Analytics Cloud Security User'; 10 | public final String AUTHENTICATED_WEBSITE = 'Authenticated Website'; 11 | public final String CHATTER_EXTERNAL_USER = 'Chatter External User'; 12 | public final String CHATTER_FREE_USER = 'Chatter Free User'; 13 | public final String CHATTER_MODERATOR_USER = 'Chatter Moderator User'; 14 | public final String COMMUNITY_PROFILE = 'Community Profile'; 15 | public final String CONTRACT_MANAGER = 'Contract Manager'; 16 | public final String CROSS_ORG_DATA_PROXY_USER = 'Cross Org Data Proxy User'; 17 | public final String CUSETOMER_PORTAL_MANAGER_CUSTOM = 'Customer Portal Manager Custom'; 18 | public final String CUSTOMER_COMMUNITY_LOGIN_USER = 'Customer Community Login User'; 19 | public final String CUSTOMER_COMMUNITY_PLUS_LOGIN_USER = 'Customer Community Plus Login User'; 20 | public final String CUSTOMER_COMMUNITY_PLUS_USER = 'Customer Community Plus User'; 21 | public final String CUSTOMER_COMMUNITY_USER = 'Customer Community User'; 22 | public final String CUSTOMER_PORTAL_MANAGER_STANDARD = 'Customer Portal Manager Standard'; 23 | public final String EXTERNAL_APPS_LOGIN_USER = 'External Apps Login User'; 24 | public final String EXTERNAL_IDENTITY_USER = 'External Identity User'; 25 | public final String FORCE_COM_APP_SUBSCRIPTION_USER = 'Force.com - App Subscription User'; 26 | public final String FORCE_COM_FREE_USER = 'Force.com - Free User'; 27 | public final String GOLD_PARTNER_USER = 'Gold Partner User'; 28 | public final String HIGHT_VOLUMNE_CUSTOMER_PORTAL_USER = 'High Volume Customer Portal User'; 29 | public final String HIGH_VOLUME_CUSTOMER_PORTAL = 'High Volume Customer Portal'; 30 | public final String IDENTITY_USER = 'Identity User'; 31 | public final String MARKETING_USER = 'Marketing User'; 32 | public final String MINIMUM_ACCESS_SALESFORCE = 'Minimum Access - Salesforce'; 33 | public final String PARTNER_APP_SUBSCRIPTION_USER = 'Partner App Subscription User'; 34 | public final String PARTNER_COMMUNITY_LOGIN_USER = 'Partner Community Login User'; 35 | public final String PARTNER_COMMUNITY_USER = 'Partner Community User'; 36 | public final String READ_ONLY = 'Read Only'; 37 | public final String SILVER_PARTNER_USER = 'Silver Partner User'; 38 | public final String SOLUTION_MANAGER = 'Solution Manager'; 39 | public final String STANDARD_GUEST = 'Standard Guest'; 40 | public final String STANDARD_PLATFORM_USER = 'Standard Platform User'; 41 | public final String STANDARD_USER = 'Standard User'; 42 | public final String SYSTEM_ADMINSTRATOR = 'System Administrator'; 43 | public final String WORK_COM_ONLY_USER = 'Work.com Only User'; 44 | } 45 | 46 | private ProfileConsts() {} 47 | } 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apex Consts 2 | 3 | Thank you for considering contributing to **Apex Consts**! 🙌 4 | We welcome contributions that improve performance, add features, fix bugs, or enhance documentation and tests. 5 | 6 | ## 🚀 How to Contribute 7 | 8 | To contribute to this project, please follow the standard GitHub fork-and-pull workflow: 9 | 10 | ### 1. Fork the Repository 11 | 12 | Start by [forking the repository](https://github.com/beyond-the-cloud-dev/apex-consts/fork) to your own GitHub account. 13 | 14 | ### 2. Clone Your Fork 15 | 16 | ```bash 17 | git clone https://github.com/YOUR_USERNAME/apex-consts.git 18 | cd apex-consts 19 | ``` 20 | 21 | ### 3. Create a New Branch 22 | 23 | ```bash 24 | git checkout -b feature/my-awesome-feature 25 | ``` 26 | 27 | ### 4. Make Your Changes 28 | 29 | Make your changes in the appropriate files. Please follow the current coding style and conventions used in the codebase. 30 | 31 | - For Apex classes: follow the singleton pattern used in existing const classes 32 | - For documentation: update relevant markdown files in `website/` 33 | 34 | If you're updating logic, add or update unit tests. 35 | 36 | ### 5. Run Tests 37 | 38 | Before committing, ensure all tests pass: 39 | 40 | ```bash 41 | sf apex run test -o dev -l RunLocalTests 42 | ``` 43 | 44 | ### 6. Commit and Push 45 | 46 | ```bash 47 | git add . 48 | git commit -m "feat: add constants for CustomObject__c" 49 | git push origin feature/my-awesome-feature 50 | ``` 51 | 52 | Use conventional commit messages: 53 | 54 | - `feat:` - New feature 55 | - `fix:` - Bug fix 56 | - `docs:` - Documentation changes 57 | - `test:` - Adding or updating tests 58 | - `chore:` - Maintenance tasks 59 | 60 | ### 7. Open a Pull Request 61 | 62 | Open a Pull Request (PR) from your fork to the main branch of the original repository: 63 | 64 | ``` 65 | https://github.com/beyond-the-cloud-dev/apex-consts 66 | ``` 67 | 68 | - Base: `main` 69 | - Compare: your feature branch 70 | 71 | Please include: 72 | 73 | - Clear description of the changes 74 | - Code examples if applicable 75 | - Reference to related issues 76 | 77 | ## ✅ Pull Request Checklist 78 | 79 | Before submitting your PR, make sure you've: 80 | 81 | - [ ] Written clear and concise commit messages 82 | - [ ] Followed existing code style and naming conventions 83 | - [ ] Added or updated relevant documentation (if applicable) 84 | - [ ] Added or updated unit tests (if applicable) 85 | - [ ] Verified that all existing tests pass 86 | - [ ] Updated the documentation site if needed 87 | 88 | ## 📝 Types of Contributions 89 | 90 | We welcome the following types of contributions: 91 | 92 | ### Code Contributions 93 | 94 | - New const classes for standard or custom objects 95 | - Additional constants for existing objects 96 | - CI/CD improvements 97 | - Test coverage improvements 98 | 99 | ### Documentation Contributions 100 | 101 | - Fix typos or clarify existing docs 102 | - Add new guides or examples 103 | - Improve API documentation 104 | - Add code snippets and best practices 105 | 106 | ### Bug Reports 107 | 108 | - Use GitHub Issues to report bugs 109 | - Include reproduction steps 110 | - Provide error messages and logs 111 | - Mention your Salesforce API version 112 | 113 | ### Feature Requests 114 | 115 | - Use GitHub Issues to suggest features 116 | - Describe the use case 117 | - Explain why it would benefit the library 118 | 119 | ## 🛠 Development Setup 120 | 121 | ```bash 122 | # Create scratch org for testing 123 | sf org create scratch -f config/project-scratch-def.json -a dev 124 | sf project deploy start -o dev 125 | 126 | # Run tests 127 | sf apex run test -o dev -l RunLocalTests 128 | ``` 129 | 130 | ## 💬 Questions? 131 | 132 | If you have questions about contributing: 133 | 134 | - Check existing [Issues](https://github.com/beyond-the-cloud-dev/apex-consts/issues) 135 | - Create a new issue for questions 136 | 137 | Thank you for helping make Apex Consts better! 🚀 138 | -------------------------------------------------------------------------------- /website/how-it-works.md: -------------------------------------------------------------------------------- 1 | # How It Works 2 | 3 | Understanding the architecture behind Apex Consts. 4 | 5 | ## Singleton Pattern 6 | 7 | Apex Consts uses the singleton pattern to ensure each constants class is instantiated only once per transaction: 8 | 9 | ```apex 10 | public class AccountConsts { 11 | // Single instance for entire transaction 12 | public static final AccountConsts INSTANCE = new AccountConsts(); 13 | 14 | // Private constructor prevents multiple instances 15 | private AccountConsts() {} 16 | } 17 | ``` 18 | 19 | ## Lazy Initialization 20 | 21 | Classes are created only when first accessed using getter properties: 22 | 23 | ```apex 24 | public class Consts { 25 | public static final AccountConsts ACCOUNT { 26 | get { 27 | return AccountConsts.INSTANCE; // Created on first access 28 | } 29 | } 30 | } 31 | ``` 32 | 33 | ### Memory Efficiency 34 | 35 | This approach minimizes heap usage: 36 | 37 | ```apex 38 | // Only AccountConsts is created 39 | String type = Consts.ACCOUNT.TYPE.PROSPECT; 40 | 41 | // ContactConsts, OpportunityConsts, etc. are NOT created 42 | // No memory wasted on unused constants 43 | ``` 44 | 45 | ## Inner Classes for Organization 46 | 47 | Constants are grouped logically using inner classes: 48 | 49 | ```apex 50 | public class AccountConsts { 51 | public final Type TYPE = new Type(); 52 | public final Rating RATING = new Rating(); 53 | 54 | public class Type { 55 | public final String PROSPECT = 'Prospect'; 56 | public final String CUSTOMER_DIRECT = 'Customer - Direct'; 57 | // ... 58 | } 59 | 60 | public class Rating { 61 | public final String HOT = 'Hot'; 62 | public final String WARM = 'Warm'; 63 | public final String COLD = 'Cold'; 64 | } 65 | } 66 | ``` 67 | 68 | This creates a clean hierarchy: 69 | - `Consts.ACCOUNT.TYPE.PROSPECT` 70 | - `Consts.ACCOUNT.RATING.HOT` 71 | 72 | ## SOLID Principles 73 | 74 | ### Open/Closed Principle 75 | 76 | The framework is open for extension but closed for modification: 77 | 78 | ```apex 79 | // Adding new constants doesn't modify existing code 80 | public class CustomObjectConsts { 81 | public static final CustomObjectConsts INSTANCE = new CustomObjectConsts(); 82 | // Your constants here 83 | } 84 | 85 | // Just add to Consts.cls 86 | public class Consts { 87 | public static final CustomObjectConsts CUSTOM_OBJECT { 88 | get { return CustomObjectConsts.INSTANCE; } 89 | } 90 | } 91 | ``` 92 | 93 | ### Single Responsibility 94 | 95 | Each class is responsible for one object's constants: 96 | - `AccountConsts` - Only Account constants 97 | - `ContactConsts` - Only Contact constants 98 | - `OpportunityConsts` - Only Opportunity constants 99 | 100 | ## Transaction Lifecycle 101 | 102 | Understanding how constants behave during a transaction: 103 | 104 | 1. **First Access** - Class instantiated once 105 | ```apex 106 | String type = Consts.ACCOUNT.TYPE.PROSPECT; 107 | // AccountConsts created here 108 | ``` 109 | 110 | 2. **Subsequent Access** - Same instance reused 111 | ```apex 112 | String rating = Consts.ACCOUNT.RATING.HOT; 113 | // Reuses AccountConsts instance from step 1 114 | ``` 115 | 116 | 3. **New Transaction** - Fresh instances 117 | ```apex 118 | // In next transaction/test, new instances created 119 | ``` 120 | 121 | ## Performance Impact 122 | 123 | The singleton + lazy loading pattern has minimal performance impact: 124 | 125 | - **One-time cost** - Class instantiation happens once 126 | - **Negligible overhead** - Getter calls are extremely fast 127 | - **Memory efficient** - Only used classes consume heap 128 | - **No SOQL** - All values are hard-coded strings 129 | 130 | ## Best Practices 131 | 132 | 1. **Don't Instantiate Directly** - Always access via `Consts` 133 | ```apex 134 | // ❌ Don't do this 135 | AccountConsts acc = new AccountConsts(); 136 | 137 | // ✅ Do this 138 | String type = Consts.ACCOUNT.TYPE.PROSPECT; 139 | ``` 140 | 141 | 2. **Use Throughout Transaction** - No need to cache values 142 | ```apex 143 | // This is fine - uses same instance 144 | for (Account acc : accounts) { 145 | if (acc.Type == Consts.ACCOUNT.TYPE.PROSPECT) { 146 | // ... 147 | } 148 | } 149 | ``` 150 | 151 | ## Next Steps 152 | 153 | - [Create Custom Constants](/creating-constants) 154 | - [View Examples](/examples) 155 | - [Best Practices](/best-practices) 156 | -------------------------------------------------------------------------------- /website/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | hero: 5 | name: "Apex Consts" 6 | text: "Constants Framework for Apex" 7 | tagline: A structured, memory-efficient approach for managing constants in Salesforce with singleton pattern and lazy initialization 8 | actions: 9 | - theme: brand 10 | text: Get Started 11 | link: /getting-started 12 | - theme: alt 13 | text: View Examples 14 | link: /examples 15 | - theme: alt 16 | text: View on GitHub 17 | link: https://github.com/beyond-the-cloud-dev/apex-consts 18 | 19 | features: 20 | - icon: 🎯 21 | title: Type-Safe Constants 22 | details: Access picklist values and API names with autocomplete support. No more typos in string literals. 23 | 24 | - icon: ⚡ 25 | title: Memory Efficient 26 | details: Singleton pattern with lazy initialization ensures classes are only instantiated when needed, reducing heap usage. 27 | 28 | - icon: 🏗️ 29 | title: Well Architected 30 | details: Follows SOLID principles - specifically Open/Closed and Single Responsibility - making it easy to extend. 31 | 32 | - icon: 📦 33 | title: Organized Structure 34 | details: Group related constants using inner classes for clean, logical organization. 35 | 36 | - icon: 🔧 37 | title: Easy to Extend 38 | details: Add your own const classes for custom objects and picklists in minutes. 39 | 40 | - icon: 🚀 41 | title: Production Ready 42 | details: Battle-tested pattern used in enterprise Salesforce implementations. Part of Apex Fluently suite. 43 | --- 44 | 45 | ## Why Apex Consts? 46 | 47 | Stop using hard-coded string literals scattered throughout your code. Apex Consts provides a centralized, type-safe way to manage constants: 48 | 49 | ::: code-group 50 | 51 | ```apex [Before ❌] 52 | Account acc = new Account( 53 | Name = 'My Account', 54 | Type = 'Prospect', // Easy to mistype 55 | Rating = 'Hot' // No autocomplete 56 | ); 57 | 58 | if (acc.Type == 'Propsect') { // Typo! Runtime error 59 | // ... 60 | } 61 | ``` 62 | 63 | ```apex [After ✅] 64 | Account acc = new Account( 65 | Name = 'My Account', 66 | Type = Consts.ACCOUNT.TYPE.PROSPECT, // Type-safe 67 | Rating = Consts.ACCOUNT.RATING.HOT // Autocomplete 68 | ); 69 | 70 | if (acc.Type == Consts.ACCOUNT.TYPE.PROSPECT) { // Compile-time safety 71 | // ... 72 | } 73 | ``` 74 | 75 | ::: 76 | 77 | ## Quick Example 78 | 79 | ```apex 80 | // Using Account constants 81 | Account acc = new Account( 82 | Name = 'Acme Corp', 83 | Type = Consts.ACCOUNT.TYPE.PROSPECT, 84 | Rating = Consts.ACCOUNT.RATING.HOT 85 | ); 86 | insert acc; 87 | 88 | // Using Contact constants 89 | Contact con = new Contact( 90 | FirstName = 'John', 91 | LastName = 'Doe', 92 | LeadSource = Consts.CONTACT.LEAD_SOURCE.WEB 93 | ); 94 | insert con; 95 | 96 | // Using Opportunity constants 97 | Opportunity opp = new Opportunity( 98 | Name = 'Big Deal', 99 | StageName = Consts.OPPORTUNITY.STAGE_NAME.PROSPECTING, 100 | Type = Consts.OPPORTUNITY.TYPE.NEW_CUSTOMER, 101 | CloseDate = Date.today().addDays(30) 102 | ); 103 | insert opp; 104 | ``` 105 | 106 | ## Features at a Glance 107 | 108 | - ✅ **Type-Safe** - Compile-time checking prevents typos 109 | - ✅ **Autocomplete** - IDE suggestions for all constants 110 | - ✅ **Memory Efficient** - Singleton pattern with lazy loading 111 | - ✅ **Organized** - Logical grouping with inner classes 112 | - ✅ **Extensible** - Easy to add custom constants 113 | - ✅ **Standard Objects** - Pre-built for Account, Contact, Opportunity, Profile 114 | - ✅ **SOLID Design** - Follows best practices and design principles 115 | 116 | ## How It Works 117 | 118 | Apex Consts uses a singleton pattern with lazy initialization: 119 | 120 | 1. **Singleton** - Each const class is instantiated only once per transaction 121 | 2. **Lazy Loading** - Classes are only created when first accessed 122 | 3. **Getter Pattern** - Properties use getters to control instantiation 123 | 124 | ```apex 125 | // First access creates instance 126 | String type = Consts.ACCOUNT.TYPE.PROSPECT; // AccountConsts created 127 | 128 | // Later accesses reuse instance 129 | String rating = Consts.ACCOUNT.RATING.HOT; // Reuses same AccountConsts 130 | 131 | // Other classes aren't created unless accessed 132 | // ContactConsts not created yet - no memory used 133 | ``` 134 | 135 | This approach minimizes heap usage and improves performance. 136 | 137 | ## Part of Apex Fluently 138 | 139 | Apex Consts is part of [Apex Fluently](https://apexfluently.beyondthecloud.dev/), a suite of production-ready Salesforce libraries by [Beyond the Cloud](https://beyondthecloud.dev). 140 | 141 | ## Get Started 142 | 143 | Ready to eliminate hard-coded strings? [Get started →](/getting-started) 144 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | contact@beyondthecloud.dev. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | --------------------------------------------------------------------------------