├── 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 |
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 |
--------------------------------------------------------------------------------