├── tools
├── apexdoc
│ ├── header.html
│ ├── apexdoc.jar
│ └── apexdoc.bat
└── codeclimate
│ └── apex
│ ├── performance.xml
│ ├── apexunit.xml
│ └── style.xml
├── .gitignore
├── .atom-build.yml
├── nebula-app-framework
├── main
│ ├── logger
│ │ ├── classes
│ │ │ ├── Logger.cls-meta.xml
│ │ │ └── Logger.cls
│ │ ├── tabs
│ │ │ └── NebulaLog__c.tab-meta.xml
│ │ ├── applications
│ │ │ └── Nebula.app-meta.xml
│ │ ├── objects
│ │ │ ├── NebulaLoggerSettings__c
│ │ │ │ ├── fields
│ │ │ │ │ └── EnableLogging__c.field-meta.xml
│ │ │ │ └── NebulaLoggerSettings__c.object-meta.xml
│ │ │ └── NebulaLog__c
│ │ │ │ ├── fields
│ │ │ │ ├── InitialClass__c.field-meta.xml
│ │ │ │ └── TransactionId__c.field-meta.xml
│ │ │ │ ├── listViews
│ │ │ │ ├── My_Logs.listView-meta.xml
│ │ │ │ └── All_Logs.listView-meta.xml
│ │ │ │ └── NebulaLog__c.object-meta.xml
│ │ └── layouts
│ │ │ └── NebulaLog__c-Log Layout.layout-meta.xml
│ ├── utilities
│ │ ├── classes
│ │ │ ├── UUID.cls-meta.xml
│ │ │ ├── Environment.cls-meta.xml
│ │ │ ├── INebulaCore.cls-meta.xml
│ │ │ ├── NebulaCore.cls-meta.xml
│ │ │ ├── Scheduler.cls-meta.xml
│ │ │ ├── CollectionUtils.cls-meta.xml
│ │ │ ├── NebulaSettings.cls-meta.xml
│ │ │ ├── ISObjectRecordTypes.cls-meta.xml
│ │ │ ├── SObjectRecordTypes.cls-meta.xml
│ │ │ ├── INebulaCore.cls
│ │ │ ├── ISObjectRecordTypes.cls
│ │ │ ├── NebulaCore.cls
│ │ │ ├── Scheduler.cls
│ │ │ ├── Environment.cls
│ │ │ ├── UUID.cls
│ │ │ ├── SObjectRecordTypes.cls
│ │ │ ├── NebulaSettings.cls
│ │ │ └── CollectionUtils.cls
│ │ └── objects
│ │ │ ├── NebulaSObjectQueryBuilderSettings__c
│ │ │ ├── NebulaSObjectQueryBuilderSettings__c.object-meta.xml
│ │ │ └── fields
│ │ │ │ └── IncludeCommonFields__c.field-meta.xml
│ │ │ └── NebulaRecordTypesSettings__c
│ │ │ ├── NebulaRecordTypesSettings__c.object-meta.xml
│ │ │ └── fields
│ │ │ ├── IncludeManagedRecordTypes__c.field-meta.xml
│ │ │ └── LazyLoad__c.field-meta.xml
│ ├── dml-management
│ │ └── classes
│ │ │ ├── DML.cls-meta.xml
│ │ │ ├── IDML.cls-meta.xml
│ │ │ ├── IDML.cls
│ │ │ └── DML.cls
│ ├── query-and-search
│ │ └── classes
│ │ │ ├── QueryDate.cls-meta.xml
│ │ │ ├── QueryField.cls-meta.xml
│ │ │ ├── IQueryField.cls-meta.xml
│ │ │ ├── IQueryFilter.cls-meta.xml
│ │ │ ├── QueryBuilder.cls-meta.xml
│ │ │ ├── QueryFilter.cls-meta.xml
│ │ │ ├── QueryOperator.cls-meta.xml
│ │ │ ├── QuerySortOrder.cls-meta.xml
│ │ │ ├── ISObjectQueryBuilder.cls-meta.xml
│ │ │ ├── ISearchQueryBuilder.cls-meta.xml
│ │ │ ├── QueryDateLiteral.cls-meta.xml
│ │ │ ├── QueryFilterScope.cls-meta.xml
│ │ │ ├── QueryNullSortOrder.cls-meta.xml
│ │ │ ├── QuerySearchGroup.cls-meta.xml
│ │ │ ├── SObjectQueryBuilder.cls-meta.xml
│ │ │ ├── SearchQueryBuilder.cls-meta.xml
│ │ │ ├── IQueryArgumentFormatter.cls-meta.xml
│ │ │ ├── QueryArgumentFormatter.cls-meta.xml
│ │ │ ├── SObjectFieldDescriber.cls-meta.xml
│ │ │ ├── AggregateResultQueryBuilder.cls-meta.xml
│ │ │ ├── IAggregateResultQueryBuilder.cls-meta.xml
│ │ │ ├── ISearchQueryBuilder.cls
│ │ │ ├── QueryNullSortOrder.cls
│ │ │ ├── QuerySortOrder.cls
│ │ │ ├── IQueryField.cls
│ │ │ ├── IQueryArgumentFormatter.cls
│ │ │ ├── QuerySearchGroup.cls
│ │ │ ├── QueryFilterScope.cls
│ │ │ ├── IQueryFilter.cls
│ │ │ ├── QueryOperator.cls
│ │ │ ├── QueryField.cls
│ │ │ ├── ISObjectQueryBuilder.cls
│ │ │ ├── IAggregateResultQueryBuilder.cls
│ │ │ ├── SObjectFieldDescriber.cls
│ │ │ ├── SearchQueryBuilder.cls
│ │ │ ├── QueryDate.cls
│ │ │ ├── QueryArgumentFormatter.cls
│ │ │ ├── QueryDateLiteral.cls
│ │ │ ├── QueryBuilder.cls
│ │ │ └── QueryFilter.cls
│ ├── sobject-repositories
│ │ └── classes
│ │ │ ├── ISObjectRepository.cls-meta.xml
│ │ │ ├── SObjectRepository.cls-meta.xml
│ │ │ ├── ISObjectRepository.cls
│ │ │ └── SObjectRepository.cls
│ └── trigger-handlers
│ │ ├── classes
│ │ ├── ISObjectTriggerHandler.cls-meta.xml
│ │ ├── SObjectTriggerHandler.cls-meta.xml
│ │ └── ISObjectTriggerHandler.cls
│ │ └── objects
│ │ └── NebulaTriggerHandlerSettings__c
│ │ ├── fields
│ │ ├── PreventRecursion__c.field-meta.xml
│ │ ├── HandlerClassesToSkip__c.field-meta.xml
│ │ └── ExecuteTriggers__c.field-meta.xml
│ │ └── NebulaTriggerHandlerSettings__c.object-meta.xml
└── tests
│ ├── logger
│ └── classes
│ │ ├── Logger_Tests.cls-meta.xml
│ │ └── Logger_Tests.cls
│ ├── utilities
│ └── classes
│ │ ├── UUID_Tests.cls-meta.xml
│ │ ├── Scheduler_Tests.cls-meta.xml
│ │ ├── CollectionUtils_Tests.cls-meta.xml
│ │ ├── Environment_Tests.cls-meta.xml
│ │ ├── NebulaSettings_Tests.cls-meta.xml
│ │ ├── SObjectRecordTypes_Tests.cls-meta.xml
│ │ ├── Scheduler_Tests.cls
│ │ ├── Environment_Tests.cls
│ │ ├── UUID_Tests.cls
│ │ ├── NebulaSettings_Tests.cls
│ │ └── SObjectRecordTypes_Tests.cls
│ ├── dml-management
│ └── classes
│ │ ├── DMLMock.cls-meta.xml
│ │ ├── DMLMock_Tests.cls-meta.xml
│ │ ├── DMLMock_Tests.cls
│ │ └── DMLMock.cls
│ ├── testing-utilities
│ └── classes
│ │ ├── TestingUtils.cls-meta.xml
│ │ └── TestingUtils.cls
│ ├── query-and-search
│ └── classes
│ │ ├── QueryDate_Tests.cls-meta.xml
│ │ ├── QueryField_Tests.cls-meta.xml
│ │ ├── QueryFilter_Tests.cls-meta.xml
│ │ ├── QueryOperator_Tests.cls-meta.xml
│ │ ├── QueryDateLiteral_Tests.cls-meta.xml
│ │ ├── SearchQueryBuilder_Tests.cls-meta.xml
│ │ ├── QueryArgumentFormatter_Tests.cls-meta.xml
│ │ ├── SObjectFieldDescriber_Tests.cls-meta.xml
│ │ ├── SObjectQueryBuilder_Tests.cls-meta.xml
│ │ ├── SObjectRepositoryMocks_Tests.cls-meta.xml
│ │ ├── AggregateResultQueryBuilder_Tests.cls-meta.xml
│ │ ├── QueryField_Tests.cls
│ │ ├── SObjectRepositoryMocks_Tests.cls
│ │ ├── QueryOperator_Tests.cls
│ │ ├── SearchQueryBuilder_Tests.cls
│ │ ├── SObjectFieldDescriber_Tests.cls
│ │ ├── AggregateResultQueryBuilder_Tests.cls
│ │ ├── QueryDate_Tests.cls
│ │ ├── QueryFilter_Tests.cls
│ │ └── QueryArgumentFormatter_Tests.cls
│ ├── sobject-repositories
│ └── classes
│ │ ├── SObjectRepositoryMocks.cls-meta.xml
│ │ ├── SObjectRepository_Tests.cls-meta.xml
│ │ └── SObjectRepositoryMocks.cls
│ └── trigger-handlers
│ └── classes
│ ├── SObjectTriggerHandler_Tests.cls-meta.xml
│ └── SObjectTriggerHandler_Tests.cls
├── sfdx-project.json
├── .forceignore
├── .codeclimate.yml
├── .gitattributes
├── manifest
└── package.xml
├── .travis.yml
├── LICENSE
└── README.md
/tools/apexdoc/header.html:
--------------------------------------------------------------------------------
1 | testing
--------------------------------------------------------------------------------
/tools/apexdoc/apexdoc.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jongpie/NebulaFramework/HEAD/tools/apexdoc/apexdoc.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Folders to exclude
2 | .settings/
3 | .sfdx/
4 | .vscode/
5 |
6 | # Files to exclude
7 | *.log
8 |
9 |
--------------------------------------------------------------------------------
/tools/apexdoc/apexdoc.bat:
--------------------------------------------------------------------------------
1 | java -jar apexdoc.jar -s ..\..\src\classes -t ..\.. -p public;protected -g https://github.com/jongpie/NebulaFramework -a header.html
--------------------------------------------------------------------------------
/.atom-build.yml:
--------------------------------------------------------------------------------
1 | cwd: '{PROJECT_PATH}'
2 | cmd: java -jar .\tools\apexdoc\apexdoc.jar -s .\src\classes -t . -p public;protected -g https://github.com/jongpie/NebulaFramework/blob/master/src/classes/ -a header.html
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/classes/Logger.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/UUID.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/dml-management/classes/DML.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/dml-management/classes/IDML.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/Environment.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/INebulaCore.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/NebulaCore.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/Scheduler.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/logger/classes/Logger_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/UUID_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryDate.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryField.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/CollectionUtils.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/NebulaSettings.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/dml-management/classes/DMLMock.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/Scheduler_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/IQueryField.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/IQueryFilter.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryBuilder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryFilter.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryOperator.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QuerySortOrder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/ISObjectRecordTypes.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/SObjectRecordTypes.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/dml-management/classes/DMLMock_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/testing-utilities/classes/TestingUtils.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/CollectionUtils_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/Environment_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/NebulaSettings_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/ISObjectQueryBuilder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/ISearchQueryBuilder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryDateLiteral.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryFilterScope.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryNullSortOrder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QuerySearchGroup.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/SObjectQueryBuilder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/SearchQueryBuilder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryDate_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryField_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryFilter_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryOperator_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/SObjectRecordTypes_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/IQueryArgumentFormatter.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryArgumentFormatter.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/SObjectFieldDescriber.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/sobject-repositories/classes/ISObjectRepository.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/sobject-repositories/classes/SObjectRepository.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/trigger-handlers/classes/ISObjectTriggerHandler.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/trigger-handlers/classes/SObjectTriggerHandler.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryDateLiteral_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/SearchQueryBuilder_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/AggregateResultQueryBuilder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/IAggregateResultQueryBuilder.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryArgumentFormatter_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/SObjectFieldDescriber_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/SObjectQueryBuilder_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/SObjectRepositoryMocks_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/sobject-repositories/classes/SObjectRepositoryMocks.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/sobject-repositories/classes/SObjectRepository_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/trigger-handlers/classes/SObjectTriggerHandler_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/AggregateResultQueryBuilder_Tests.cls-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 40.0
4 | Active
5 |
6 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/tabs/NebulaLog__c.tab-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | false
5 | Custom83: Pencil
6 |
7 |
--------------------------------------------------------------------------------
/sfdx-project.json:
--------------------------------------------------------------------------------
1 | {
2 | "packageDirectories": [
3 | {
4 | "path": "nebula-app-framework",
5 | "default": true
6 | }
7 | ],
8 | "namespace": "Nebula",
9 | "sfdcLoginUrl": "https://nebulaframework-dev.my.salesforce.com",
10 | "sourceApiVersion": "39.0"
11 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/applications/Nebula.app-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | NebulaLog__c
4 | Large
5 |
6 | NebulaLog__c
7 |
8 |
--------------------------------------------------------------------------------
/.forceignore:
--------------------------------------------------------------------------------
1 | # List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status
2 | # More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm
3 | #
4 |
5 | package.xml
6 |
7 | # LWC configuration files
8 | **/jsconfig.json
9 | **/.eslintrc.json
10 |
11 | # LWC Jest
12 | **/__tests__/**
--------------------------------------------------------------------------------
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | engines:
2 | apexmetrics:
3 | enabled: true
4 | config:
5 | rulesets: "./tools/codeclimate/apex/apexunit.xml,./tools/codeclimate/apex/complexity.xml,./tools/codeclimate/apex/performance.xml,./tools/codeclimate/apex/security.xml,./tools/codeclimate/apex/style.xml"
6 | exclude_paths:
7 | - "**Tests.cls"
8 | ratings:
9 | paths:
10 | - "**.cls"
11 | - "**.trigger"
12 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/objects/NebulaSObjectQueryBuilderSettings__c/NebulaSObjectQueryBuilderSettings__c.object-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hierarchy
4 | false
5 |
6 | Public
7 |
8 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/objects/NebulaLoggerSettings__c/fields/EnableLogging__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | EnableLogging__c
4 | true
5 | false
6 |
7 | false
8 | Checkbox
9 |
10 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/objects/NebulaLoggerSettings__c/NebulaLoggerSettings__c.object-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hierarchy
4 | Controls the behavior of the class Logger.cls
5 | false
6 |
7 | Public
8 |
9 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/trigger-handlers/objects/NebulaTriggerHandlerSettings__c/fields/PreventRecursion__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | PreventRecursion__c
4 | true
5 | false
6 |
7 | false
8 | Checkbox
9 |
10 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/trigger-handlers/objects/NebulaTriggerHandlerSettings__c/fields/HandlerClassesToSkip__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | HandlerClassesToSkip__c
4 | false
5 |
6 | false
7 | false
8 | TextArea
9 |
10 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/objects/NebulaSObjectQueryBuilderSettings__c/fields/IncludeCommonFields__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | IncludeCommonFields__c
4 | true
5 | false
6 |
7 | false
8 | Checkbox
9 |
10 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default line return behavior, in case people don't have core.autocrlf set.
2 | * text=auto eol=lf
3 |
4 | # Common git file types
5 | .gitattributes text eol=lf
6 | .gitignore text eol=lf
7 | *.md text eol=lf
8 |
9 | # Salesforce-specfic file types
10 | *.app text eol=lf
11 | *.cls text eol=lf
12 | *.cmp text eol=lf
13 | *.component text eol=lf
14 | *.css text eol=lf
15 | *.html text eol=lf
16 | *.js text eol=lf
17 | *.page text eol=lf
18 | *.trigger text eol=lf
19 | *.xml text eol=lf
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/objects/NebulaRecordTypesSettings__c/NebulaRecordTypesSettings__c.object-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hierarchy
4 | Controls the behavior of the class SObjectRecordTypes.cls
5 | false
6 |
7 | Public
8 |
9 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/ISearchQueryBuilder.cls:
--------------------------------------------------------------------------------
1 | public interface ISearchQueryBuilder {
2 |
3 | ISearchQueryBuilder cacheResults();
4 |
5 | ISearchQueryBuilder inQuerySearchGroup(QuerySearchGroup searchGroup);
6 | ISearchQueryBuilder withHighlight(Boolean withHighlight);
7 | ISearchQueryBuilder withSpellCorrection(Boolean withSpellCorrection);
8 |
9 | String getQuery();
10 |
11 | List getFirstSearchResult();
12 | List> getSearchResults();
13 |
14 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/trigger-handlers/objects/NebulaTriggerHandlerSettings__c/NebulaTriggerHandlerSettings__c.object-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hierarchy
4 | Controls the behavior of the class SObjectTriggerHandler.cls
5 | false
6 |
7 | Public
8 |
9 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/objects/NebulaLog__c/fields/InitialClass__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | InitialClass__c
4 | false
5 |
6 | 255
7 | false
8 | false
9 | false
10 | Text
11 | false
12 |
13 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/objects/NebulaLog__c/listViews/My_Logs.listView-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | My_Logs
4 | NAME
5 | TransactionId__c
6 | InitialClass__c
7 | CREATED_DATE
8 | UPDATEDBY_USER
9 | LAST_UPDATE
10 | Mine
11 |
12 |
13 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/objects/NebulaLog__c/fields/TransactionId__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | TransactionId__c
4 | false
5 | true
6 |
7 | 36
8 | true
9 | false
10 | false
11 | Text
12 | true
13 |
14 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/objects/NebulaLog__c/listViews/All_Logs.listView-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | All_Logs
4 | NAME
5 | TransactionId__c
6 | InitialClass__c
7 | CREATEDBY_USER
8 | CREATED_DATE
9 | UPDATEDBY_USER
10 | LAST_UPDATE
11 | Everything
12 |
13 |
14 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryNullSortOrder.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public enum QueryNullSortOrder { FIRST, LAST }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QuerySortOrder.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public enum QuerySortOrder { ASCENDING, DESCENDING }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/IQueryField.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface IQueryField {
14 |
15 | String getValue();
16 |
17 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/trigger-handlers/classes/ISObjectTriggerHandler.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Trigger Handler
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface ISObjectTriggerHandler {
14 |
15 | void execute();
16 |
17 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/IQueryArgumentFormatter.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface IQueryArgumentFormatter {
14 |
15 | String getValue();
16 |
17 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QuerySearchGroup.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public enum QuerySearchGroup { ALL_FIELDS, NAME_FIELDS, EMAIL_FIELDS, PHONE_FIELDS, SIDEBAR_FIELDS }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/INebulaCore.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Configuration
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface INebulaCore {
14 |
15 | String getClassName();
16 | NebulaCore.Module getClassModule();
17 |
18 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/ISObjectRecordTypes.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Record Types
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface ISObjectRecordTypes {
14 |
15 | // Setup methods
16 | Schema.SObjectType getSObjectType();
17 |
18 | // Getter methods
19 | Map getAllById();
20 | Map getAllByDeveloperName();
21 |
22 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/objects/NebulaRecordTypesSettings__c/fields/IncludeManagedRecordTypes__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | IncludeManagedRecordTypes__c
4 | true
5 | Determines if managed record types are included in queries. If you do not use any managed record types, then you can disable this.
6 | false
7 | Determines if managed record types are included in queries. If you do not use any managed record types, then you can disable this.
8 |
9 | false
10 | Checkbox
11 |
12 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryFilterScope.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description Enum of possible values for SOQL's optional USING SCOPE
11 | * Salesforce docs: developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_using_scope.htm
12 | *
13 | */
14 | public enum QueryFilterScope { EVERYTHING, DELEGATED, TEAM, MINE, MY_TERRITORY, MY_TEAM_TERRITORY }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/objects/NebulaRecordTypesSettings__c/fields/LazyLoad__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | LazyLoad__c
4 | true
5 | Determines if a separate query is executed for each SObject (lazy load enabled), or if a single query is used to pre-load all record types (lazy load disabled)
6 | false
7 | Determines if a separate query is executed for each SObject (lazy load enabled), or if a single query is used to pre-load all record types (lazy load disabled)
8 |
9 | false
10 | Checkbox
11 |
12 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/trigger-handlers/objects/NebulaTriggerHandlerSettings__c/fields/ExecuteTriggers__c.field-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ExecuteTriggers__c
4 | true
5 | Controls if any trigger handler classes run its execute() method. This should always be enabled unless you are doing a data fix, etc and need to temporarily disable all triggers.
6 | false
7 | Controls if any trigger handler classes run its execute() method. This should always be enabled unless you are doing a data fix, etc and need to temporarily disable all triggers.
8 |
9 | false
10 | Checkbox
11 |
12 |
--------------------------------------------------------------------------------
/manifest/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | *
5 | ApexClass
6 |
7 |
8 | Nebula
9 | CustomApplication
10 |
11 |
12 | NebulaLog__c
13 | NebulaLoggerSettings__c
14 | NebulaRecordTypesSettings__c
15 | NebulaSObjectQueryBuilderSettings__c
16 | NebulaTriggerHandlerSettings__c
17 | CustomObject
18 |
19 |
20 | NebulaLog__c
21 | CustomTab
22 |
23 |
24 | NebulaLog__c-Log Layout
25 | Layout
26 |
27 | 39.0
28 |
29 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: true
2 | os: trusty
3 | cache: false
4 |
5 | env:
6 | - URL=https://developer.salesforce.com/media/salesforce-cli/sfdx-linux-amd64.tar.xz
7 |
8 | before_install:
9 | #- openssl aes-256-cbc -K $encrypted_b1fbf710b918_key -iv $encrypted_b1fbf710b918_iv
10 | # -in assets/server.key.enc -out assets/server.key -d
11 | - export SFDX_AUTOUPDATE_DISABLE=false
12 | - export SFDX_USE_GENERIC_UNIX_KEYCHAIN=true
13 | - export SFDX_DOMAIN_RETRY=300
14 | - export SFDX_DISABLE_APP_HUB=true
15 | - export SFDX_LOG_LEVEL=DEBUG
16 | - mkdir sfdx
17 | - wget -qO- $URL | tar xJ -C sfdx --strip-components 1
18 | - "./sfdx/install"
19 | - export PATH=./sfdx/$(pwd):$PATH
20 | - sfdx --version
21 | - sfdx plugins --core
22 | - echo $SFDX_URL > sfdx_url_file
23 | - sfdx force:auth:sfdxurl:store --sfdxurlfile sfdx_url_file --setalias nebula_ci
24 |
25 | script:
26 | - sfdx force:config:set apiVersion=39.0
27 | - sfdx force:source:deploy --checkonly --manifest ./manifest/package.xml --testlevel RunLocalTests --targetusername nebula_ci --verbose
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Jonathan Gillespie
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 |
23 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryField_Tests.cls:
--------------------------------------------------------------------------------
1 | @isTest
2 | private class QueryField_Tests {
3 |
4 | @isTest
5 | static void it_should_return_string_for_sobject_field_name() {
6 | System.assertEquals('CreatedDate', new QueryField(Schema.Lead.CreatedDate).getValue());
7 | }
8 |
9 | @isTest
10 | static void it_should_return_string_for_parent_sobject_field_name() {
11 | List fieldChain = new List{
12 | Schema.Contact.AccountId, Schema.Account.CreatedById, Schema.User.Name
13 | };
14 | System.assertEquals('Account.CreatedBy.Name', new QueryField(fieldChain).getValue());
15 | }
16 |
17 | @isTest
18 | static void it_should_be_callable_multiple_times_without_pop_removing_field_references() {
19 | List fieldChain = new List{
20 | Schema.Contact.AccountId, Schema.Account.Name
21 | };
22 | QueryField queryField = new QueryField(fieldChain);
23 | String expected = 'Account.Name';
24 | for(Integer i = 0; i < 5; i++) {
25 | System.assertEquals(expected, queryField.getValue());
26 | }
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/IQueryFilter.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface IQueryFilter {
14 |
15 | // Setter methods
16 | IQueryFilter filterByField(QueryField queryField, QueryOperator operator, Object providedValue);
17 | IQueryFilter filterByQueryDate(QueryDate queryDateToFilter, QueryOperator operator, Integer providedValue);
18 | IQueryFilter filterBySubquery(QueryOperator inOrNotIn, Schema.SObjectField lookupFieldOnRelatedSObject);
19 | IQueryFilter filterBySubquery(Schema.SObjectField lookupField, QueryOperator inOrNotIn, Schema.SObjectField lookupFieldOnRelatedSObject);
20 |
21 | IQueryFilter andFilterBy(List queryFilters);
22 | IQueryFilter orFilterBy(List queryFilters);
23 |
24 | // Getter methods
25 | String getValue();
26 |
27 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/sobject-repositories/classes/ISObjectRepository.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Repository
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface ISObjectRepository {
14 |
15 | // Setup methods
16 | Schema.SObjectType getSObjectType();
17 |
18 | // SOQL
19 | SObject getById(Id recordId);
20 | List getById(List recordIdList);
21 | List get(IQueryFilter queryFilter);
22 | List get(List queryFilters);
23 | List getByIdAndQueryFilters(Set idSet, List queryFilters);
24 | List getByIdAndQueryFilters(List idList, List queryFilters);
25 |
26 | // SOSL
27 | List getSearchResults(String searchTerm);
28 | List getSearchResults(String searchTerm, QuerySearchGroup searchGroup);
29 | List getSearchResults(String searchTerm, QuerySearchGroup searchGroup, List queryFilters);
30 |
31 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/NebulaCore.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Configuration
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public abstract class NebulaCore implements INebulaCore {
14 |
15 | public enum Module { QUERY_BUILDER, RECORD_TYPES, REPOSITORY, SETTINGS, TRIGGER_HANDLER }
16 |
17 | public static final String TRANSACTION_ID;
18 | public static String INITIAL_CLASS {get; private set;}
19 |
20 | static {
21 | NebulaCore.TRANSACTION_ID = new UUID().getValue();
22 | System.debug('NebulaCore.TRANSACTION_ID=' + NebulaCore.TRANSACTION_ID);
23 | }
24 |
25 | protected final Module currentModule;
26 |
27 | protected NebulaCore() {
28 | if(NebulaCore.INITIAL_CLASS == null) NebulaCore.INITIAL_CLASS = this.getClassName();
29 | }
30 |
31 | public String getClassName() {
32 | return String.valueOf(this).split(':')[0];
33 | }
34 |
35 | public NebulaCore.Module getClassModule() {
36 | return this.currentModule;
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/dml-management/classes/IDML.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Repository
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface IDML {
14 |
15 | List insertRecords(SObject record);
16 | List insertRecords(List recordList);
17 | List updateRecords(SObject record);
18 | List updateRecords(List recordList);
19 | List upsertRecords(SObject record);
20 | List upsertRecords(List recordList);
21 | List undeleteRecords(SObject record);
22 | List undeleteRecords(List recordList);
23 | List deleteRecords(SObject record);
24 | List deleteRecords(List recordList);
25 | List hardDeleteRecords(SObject record);
26 | List hardDeleteRecords(List recordList);
27 |
28 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/Scheduler_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class Scheduler_Tests {
7 |
8 | private static final String SCHEDULABLE_JOB_ID = '7';
9 | private static final String DAILY_CRON_EXP = '0 59 23 * * ?';
10 |
11 | private class TestSchedulable implements Schedulable {
12 | public void execute(SchedulableContext sc) {}
13 | }
14 |
15 | @isTest
16 | static void it_should_successfully_schedule_daily() {
17 | String jobId = new Scheduler(new TestSchedulable()).scheduleDaily(SCHEDULABLE_JOB_ID, '59', '23');
18 | CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE Id = :jobId];
19 | System.assertEquals(DAILY_CRON_EXP, ct.CronExpression);
20 | }
21 |
22 | @isTest
23 | static void it_should_successfully_schedule_hourly() {
24 | String jobId = new Scheduler(new TestSchedulable()).scheduleHourly(SCHEDULABLE_JOB_ID, '59');
25 | CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE Id = :jobId];
26 | System.assertEquals(String.format(Scheduler.HOURLY_CRON, new List{'59'}), ct.CronExpression);
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/Scheduler.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Asynchronous Apex
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public class Scheduler {
14 |
15 | //CRON order - Seconds, Minutes, Hours, Day_of_month, Month, Day_of_week, Optional_year
16 | public final static String DAILY_CRON = '0 {0} {1} * * ?';
17 | public final static String HOURLY_CRON = '0 {0} * * * ?';
18 | private final Schedulable scheduledClass;
19 |
20 | public Scheduler (Schedulable scheduledClass) {
21 | this.scheduledClass = scheduledClass;
22 | }
23 |
24 | public String scheduleHourly(String jobName, String startingMinuteInHour) {
25 | String hourlyCRON = String.format(HOURLY_CRON, new List{startingMinuteInHour});
26 | return this.schedule(jobName, hourlyCRON);
27 | }
28 |
29 | public String scheduleDaily(String jobName, String startingHour, String startingMinute) {
30 | String dailyCRON = String.format(DAILY_CRON, new List{startingHour, startingMinute});
31 | return this.schedule(jobName, dailyCRON);
32 | }
33 |
34 | public String schedule(String jobName, String cronExpression) {
35 | return System.schedule(jobName, cronExpression, this.scheduledClass);
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/Environment_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class Environment_Tests {
7 |
8 | @isTest
9 | static void it_should_return_base_url() {
10 | System.assert(Environment.BaseUrl.endsWithIgnoreCase('.salesforce.com'));
11 | }
12 |
13 | @isTest
14 | static void it_should_return_instance_name() {
15 | Organization org = [SELECT Id, InstanceName FROM Organization];
16 | System.assertEquals(org.InstanceName, Environment.InstanceName);
17 | }
18 |
19 | @isTest
20 | static void it_should_return_is_sandbox() {
21 | Organization org = [SELECT Id, IsSandbox FROM Organization];
22 | System.assertEquals(org.IsSandbox, Environment.IsSandbox);
23 | }
24 |
25 | @isTest
26 | static void it_should_return_name() {
27 | Organization org = [SELECT Id, Name FROM Organization];
28 | System.assertEquals(org.Name, Environment.Name);
29 | }
30 |
31 | @isTest
32 | static void it_should_return_namespace_prefix() {
33 | Organization org = [SELECT Id, NamespacePrefix FROM Organization];
34 | System.assertEquals(org.NamespacePrefix, Environment.NamespacePrefix);
35 | }
36 |
37 | @isTest
38 | static void it_should_return_type() {
39 | Organization org = [SELECT Id, OrganizationType FROM Organization];
40 | System.assertEquals(org.OrganizationType, Environment.Type);
41 | }
42 |
43 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/Environment.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Metadata
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public without sharing class Environment {
14 |
15 | public static String BaseUrl {
16 | get {return URL.getSalesforceBaseUrl().toExternalForm();}
17 | private set;
18 | }
19 |
20 | public static String InstanceName {
21 | get {return organization.InstanceName;}
22 | private set;
23 | }
24 |
25 | /**
26 | * @description Specifies if the org is a production environment or sandbox
27 | * returns true if it's a sandbox
28 | */
29 | public static Boolean IsSandbox {
30 | get {return organization.IsSandbox;}
31 | private set;
32 | }
33 |
34 | public static String Name {
35 | get {return organization.Name;}
36 | private set;
37 | }
38 |
39 | public static String NamespacePrefix {
40 | get {return organization.NamespacePrefix;}
41 | private set;
42 | }
43 |
44 | public static String Type {
45 | get {return organization.OrganizationType;}
46 | private set;
47 | }
48 |
49 | private static Organization organization {
50 | get {
51 | if(organization == null) organization = [SELECT Id, InstanceName, IsSandbox, Name, NamespacePrefix, OrganizationType FROM Organization];
52 | return organization;
53 | }
54 | private set;
55 | }
56 |
57 | }
--------------------------------------------------------------------------------
/tools/codeclimate/apex/performance.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 | The Performance ruleset contains a collection of good practices which should be followed.
9 |
10 |
11 |
16 |
17 | New objects created within loops should be checked to see if they can created outside them and reused.
18 |
19 | 3
20 |
21 | accounts = [SELECT Id FROM Account];
25 | }
26 | }
27 | }
28 | ]]>
29 |
30 |
31 |
32 |
37 | Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop.
38 | 3
39 |
40 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/UUID.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Utils
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public without sharing class UUID {
14 |
15 | public static Boolean isEmpty(String uuid) {
16 | return String.isBlank(uuid) || uuid == '00000000-0000-0000-0000-000000000000';
17 | }
18 |
19 | public static Boolean isValid(String uuid) {
20 | if(isEmpty(uuid)) return false;
21 |
22 | String uuidRegEx = '[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}';
23 | Pattern uuidPattern = Pattern.compile(uuidRegEx);
24 | Matcher uuidMatcher = uuidPattern.matcher(uuid.toUpperCase());
25 |
26 | return uuidMatcher.matches();
27 | }
28 |
29 | private String value;
30 |
31 | public UUID() {
32 | this.setValue();
33 | }
34 |
35 | public String getValue() {
36 | return value;
37 | }
38 |
39 | private void setValue() {
40 | Blob generatedBlob = Crypto.GenerateAESKey(128);
41 | String hex = EncodingUtil.ConvertTohex(generatedBlob);
42 | this.value = this.formatValue(hex);
43 | }
44 |
45 | private String formatValue(String unformattedValue) {
46 | // Remove any non-alphanumeric characters. Should be unnecessary, but better to be safe than sorry.
47 | unformattedValue = unformattedValue.replaceAll('[^a-zA-Z0-9]', '');
48 |
49 | String formattedValue = unformattedValue.substring(0, 8)
50 | + '-' + unformattedValue.substring(8, 12)
51 | + '-' + unformattedValue.substring(12, 16)
52 | + '-' + unformattedValue.substring(16, 20)
53 | + '-' + unformattedValue.substring(20);
54 |
55 | return formattedValue.toUpperCase();
56 | }
57 |
58 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryOperator.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description Provides all of the operators needed for SOQL/SOSL queries and minimizes the use of strings within the framework
11 | * Salesforce docs: developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_comparisonoperators.htm
12 | *
13 | */
14 | public without sharing class QueryOperator extends NebulaCore {
15 |
16 | private String value;
17 |
18 | private QueryOperator(String value) {
19 | this.currentModule = NebulaCore.Module.QUERY_BUILDER;
20 |
21 | this.value = value;
22 | }
23 |
24 | public String getValue() {
25 | return this.value;
26 | }
27 |
28 | public static final QueryOperator EQUALS = new QueryOperator('=');
29 | public static final QueryOperator NOT_EQUAL_TO = new QueryOperator('!=');
30 | public static final QueryOperator GREATER_THAN = new QueryOperator('>');
31 | public static final QueryOperator GREATER_THAN_OR_EQUAL_TO = new QueryOperator('>=');
32 | public static final QueryOperator LESS_THAN = new QueryOperator('<');
33 | public static final QueryOperator LESS_THAN_OR_EQUAL_TO = new QueryOperator('<=');
34 | public static final QueryOperator IS_IN = new QueryOperator('IN');
35 | public static final QueryOperator IS_NOT_IN = new QueryOperator('NOT IN');
36 | public static final QueryOperator INCLUDES = new QueryOperator('INCLUDES');
37 | public static final QueryOperator EXCLUDES = new QueryOperator('EXCLUDES');
38 | public static final QueryOperator IS_LIKE = new QueryOperator('LIKE');
39 | public static final QueryOperator IS_NOT_LIKE = new QueryOperator('NOT LIKE');
40 |
41 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryField.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description Used to dynamically generate field string for SObject fields, including parent fields.
11 | *
12 | */
13 | public without sharing class QueryField extends NebulaCore implements IQueryField, Comparable {
14 |
15 | private final List fields;
16 | private final String value;
17 |
18 | public QueryField(SObjectField field) {
19 | this(new List{field});
20 | }
21 |
22 | public QueryField(List fields) {
23 | this.currentModule = NebulaCore.Module.QUERY_BUILDER;
24 |
25 | this.fields = fields;
26 | this.value = this.parseFields();
27 | }
28 |
29 | public String getValue() {
30 | return this.value;
31 | }
32 |
33 | private String parseFields() {
34 | if(this.fields.size() == 1) return String.valueOf(this.fields[0]);
35 |
36 | //Remove the last field from the list to iterate through so only the parent relationships are hopped
37 | List fieldsToIterate = this.fields.clone();
38 | SObjectField lastField = (SObjectField) CollectionUtils.pop(fieldsToIterate);
39 | List fieldChain = new List();
40 | for(SObjectField parentField : fieldsToIterate) {
41 | fieldChain.add(parentField.getDescribe().getRelationshipName());
42 | }
43 | // Return the fully qualified field name
44 | return String.join(fieldChain, '.') + '.' + lastField.getDescribe().getName();
45 | }
46 |
47 |
48 | public Integer compareTo(Object compareTo) {
49 | QueryField compareToQueryField = (QueryField)compareTo;
50 | if(this.getValue() == compareToQueryField.getValue()) return 0;
51 | if(this.getValue() > compareToQueryField.getValue()) return 1;
52 | return -1;
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/SObjectRepositoryMocks_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class SObjectRepositoryMocks_Tests {
7 |
8 | @isTest
9 | static void it_should_fake_returning_by_id() {
10 | Id testId = getTestId();
11 |
12 | SObject returnedObj = new SObjectRepositoryMocks.Base(null).getById(testId);
13 |
14 | System.assert(returnedObj.Id == testId);
15 | }
16 |
17 | @isTest
18 | static void it_should_fake_returning_by_field_and_value() {
19 | Id testId = getTestId();
20 | QueryField field = getField();
21 |
22 | List queryFilters = new List{new QueryFilter().filterByField(field, QueryOperator.EQUALS, getFieldValue())};
23 | SObject returnedObj = new SObjectRepositoryMocks.Base(null).getByIdAndQueryFilters(new Set{testId}, queryFilters)[0];
24 |
25 | //System.assertEquals(getFieldValue(), returnedObj.get(String.valueOf(field.getValue())));
26 | }
27 |
28 | @isTest
29 | static void it_should_return_list_of_sobjects_when_mocking_sosl_search() {
30 | System.assert(new SObjectRepositoryMocks.Base().getSearchResults(getFieldValue(), QuerySearchGroup.ALL_FIELDS) instanceof List);
31 | }
32 |
33 | @isTest
34 | static void it_should_return_list_of_sobjects_when_mocking_sosl_search_with_passed_objects() {
35 | Contact con = new Contact();
36 | ISObjectRepository base = new SObjectRepositoryMocks.Base().with(new List{con});
37 |
38 | System.assert(base.getSearchResults(getFieldValue(),QuerySearchGroup.ALL_FIELDS) instanceof List);
39 | }
40 |
41 | static QueryField getField() {
42 | return new QueryField(Schema.Lead.LeadSource);
43 | }
44 |
45 | static String getFieldValue() {
46 | return 'Web';
47 | }
48 |
49 | static Id getTestId() {
50 | return TestingUtils.generateId(Schema.Lead.SObjectType);
51 | }
52 |
53 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/UUID_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class UUID_Tests {
7 |
8 | @isTest
9 | static void it_should_consider_all_zeroes_string_to_be_empty() {
10 | System.assert(UUID.isEmpty('00000000-0000-0000-0000-000000000000'));
11 | }
12 |
13 | @isTest
14 | static void it_should_create_a_new_UUID() {
15 | String generatedUUID = new UUID().getValue();
16 | System.assertEquals(36, generatedUUID.length());
17 | }
18 |
19 | @isTest
20 | static void it_should_reuse_a_UUID_on_subsequent_calls_to_getValue() {
21 | UUID theUUID = new UUID();
22 | String originalValue = theUUID.getValue();
23 |
24 | for(Integer i = 0; i < 5; i++) {
25 | System.assertEquals(originalValue, theUUID.getValue());
26 | }
27 | }
28 |
29 | @isTest
30 | static void it_should_verify_that_a_UUID_is_a_UUID() {
31 | String generatedUUID = new UUID().getValue();
32 | System.assert(UUID.isValid(generatedUUID));
33 | }
34 |
35 | @isTest
36 | static void it_should_consider_null_string_an_empty_UUID() {
37 | System.assert(UUID.isEmpty(null));
38 | }
39 |
40 | @isTest
41 | static void it_should_not_consider_an_empty_string_a_UUID() {
42 | System.assertEquals(false, UUID.isValid(''));
43 | }
44 |
45 | @isTest
46 | static void it_should_not_consider_null_a_UUID() {
47 | System.assertEquals(false, UUID.isValid(null));
48 | }
49 |
50 | @isTest
51 | static void it_should_validate_a_UUID_in_upper_case() {
52 | String exampleUUID = 'f3665813-1a60-4924-ad9b-23a9cef17d80'.toUpperCase();
53 | System.assertEquals(true, UUID.isValid(exampleUUID));
54 | }
55 |
56 | @isTest
57 | static void it_should_validate_a_UUID_in_lower_case() {
58 | String exampleUUID = 'f3665813-1a60-4924-ad9b-23a9cef17d80'.toLowerCase();
59 | System.assertEquals(true, UUID.isValid(exampleUUID));
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/ISObjectQueryBuilder.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface ISObjectQueryBuilder {
14 |
15 | ISObjectQueryBuilder cacheResults();
16 |
17 | // Field methods
18 | ISObjectQueryBuilder addAllFields();
19 | ISObjectQueryBuilder addAllStandardFields();
20 | ISObjectQueryBuilder addAllCustomFields();
21 | ISObjectQueryBuilder addAllReadableFields();
22 | ISObjectQueryBuilder addAllEditableFields();
23 | ISObjectQueryBuilder addFields(List queryFields);
24 | ISObjectQueryBuilder addFields(Schema.FieldSet fieldSet);
25 |
26 | // Parent-to-child relationship query methods
27 | ISObjectQueryBuilder includeChildrenRecords(Schema.SObjectField childToParentRelationshipField, ISObjectQueryBuilder sobjectQueryBuilder);
28 |
29 | // Filter methods
30 | ISObjectQueryBuilder filterBy(IQueryFilter queryFilter);
31 | ISObjectQueryBuilder filterBy(List queryFilters);
32 |
33 | // Order By methods
34 | ISObjectQueryBuilder orderBy(IQueryField orderByQueryField);
35 | ISObjectQueryBuilder orderBy(IQueryField orderByQueryField, QuerySortOrder sortOrder);
36 | ISObjectQueryBuilder orderBy(IQueryField orderByQueryField, QuerySortOrder sortOrder, QueryNullSortOrder nullsSortOrder);
37 |
38 | // Additional query option methods
39 | ISObjectQueryBuilder limitCount(Integer limitCount);
40 | ISObjectQueryBuilder offset(Integer numberOfRowsToSkip);
41 | ISObjectQueryBuilder forReference();
42 | ISObjectQueryBuilder forUpdate();
43 | ISObjectQueryBuilder forView();
44 | ISObjectQueryBuilder usingScope(QueryFilterScope filterScope);
45 |
46 | // Query string methods
47 | Database.QueryLocator getQueryLocator();
48 | String getQuery();
49 | String getSearchQuery();
50 | String getChildQuery(Schema.SObjectField childToParentRelationshipField);
51 |
52 | // Query execution methods
53 | SObject getFirstQueryResult();
54 | List getQueryResults();
55 |
56 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryOperator_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class QueryOperator_Tests {
7 |
8 | @isTest
9 | static void it_should_return_EQUALS_string() {
10 | System.assertEquals('=', QueryOperator.EQUALS.getValue());
11 | }
12 |
13 | @isTest
14 | static void it_should_return_NOT_EQUAL_TO_string() {
15 | System.assertEquals('!=', QueryOperator.NOT_EQUAL_TO.getValue());
16 | }
17 |
18 | @isTest
19 | static void it_should_return_GREATER_THAN_string() {
20 | System.assertEquals('>', QueryOperator.GREATER_THAN.getValue());
21 | }
22 |
23 | @isTest
24 | static void it_should_return_GREATER_THAN_OR_EQUAL_TO_string() {
25 | System.assertEquals('>=', QueryOperator.GREATER_THAN_OR_EQUAL_TO.getValue());
26 | }
27 |
28 | @isTest
29 | static void it_should_return_LESS_THAN_string() {
30 | System.assertEquals('<', QueryOperator.LESS_THAN.getValue());
31 | }
32 |
33 | @isTest
34 | static void it_should_return_LESS_THAN_OR_EQUAL_TO_string() {
35 | System.assertEquals('<=', QueryOperator.LESS_THAN_OR_EQUAL_TO.getValue());
36 | }
37 |
38 | @isTest
39 | static void it_should_return_IS_IN_string() {
40 | System.assertEquals('IN', QueryOperator.IS_IN.getValue());
41 | }
42 |
43 | @isTest
44 | static void it_should_return_IS_NOT_IN_string() {
45 | System.assertEquals('NOT IN', QueryOperator.IS_NOT_IN.getValue());
46 | }
47 |
48 | @isTest
49 | static void it_should_return_INCLUDES_string() {
50 | System.assertEquals('INCLUDES', QueryOperator.INCLUDES.getValue());
51 | }
52 |
53 | @isTest
54 | static void it_should_return_EXCLUDES_string() {
55 | System.assertEquals('EXCLUDES', QueryOperator.EXCLUDES.getValue());
56 | }
57 |
58 | @isTest
59 | static void it_should_return_IS_LIKE_string() {
60 | System.assertEquals('LIKE', QueryOperator.IS_LIKE.getValue());
61 | }
62 |
63 | @isTest
64 | static void it_should_return_IS_NOT_LIKE_string() {
65 | System.assertEquals('NOT LIKE', QueryOperator.IS_NOT_LIKE.getValue());
66 | }
67 |
68 | }
--------------------------------------------------------------------------------
/tools/codeclimate/apex/apexunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 | These rules deal with different problems that can occur with Apex unit tests.
9 |
10 |
11 |
16 |
17 | Apex unit tests should include at least one assertion. This makes the tests more robust, and using assert
18 | with messages provide the developer a clearer idea of what the test does.
19 |
20 | 3
21 |
22 |
33 |
34 |
35 |
40 |
41 | Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database data for unexpected modification by tests.
42 |
43 | 3
44 |
45 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/testing-utilities/classes/TestingUtils.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Utils
9 | *
10 | * @description TODO
11 | *
12 | */
13 | @isTest
14 | public class TestingUtils {
15 |
16 | public static List insertedRecords = new List();
17 | public static List upsertedRecords = new List();
18 | public static List updatedRecords = new List();
19 | public static List deletedRecords = new List();
20 | public static List undeletedRecords = new List();
21 |
22 | private static Integer startingNumber = 1;
23 |
24 | public static String generateId(Schema.SObjectType sobjectType) {
25 | String result = String.valueOf(startingNumber++);
26 | return sobjectType.getDescribe().getKeyPrefix() + '0'.repeat(12-result.length()) + result;
27 | }
28 |
29 | public static void generateIds(List records) {
30 | for(SObject record : records) record.Id = record.Id != null ? record.Id : generateId(record.getSObjectType());
31 | }
32 |
33 | public static SObject setReadOnlyField(SObject sobj, Schema.SObjectField fieldName, Object value) {
34 | return setReadOnlyField(sobj, new Map{fieldName => value});
35 | }
36 |
37 | public static SObject setReadOnlyField(SObject sobj, Map changesToFields) {
38 | String serializedRecord = JSON.serialize(sobj);
39 | Map deserializedRecordMap = (Map)JSON.deserializeUntyped(serializedRecord);
40 |
41 | // Loop through the deserialized record map and put the field & value
42 | // Since it's a map, if the field already exists on the SObject, it's updated (or added if it wasn't there already)
43 | for(Schema.SObjectField sobjectField : changesToFields.keySet()) {
44 | String fieldName = sobjectField.getDescribe().getName();
45 | deserializedRecordMap.put(fieldName, changesToFields.get(sobjectField));
46 | }
47 |
48 | serializedRecord = JSON.serialize(deserializedRecordMap);
49 | return (SObject)JSON.deserialize(serializedRecord, SObject.class);
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/SearchQueryBuilder_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class SearchQueryBuilder_Tests {
7 |
8 | @isTest
9 | static void it_should_be_usable_after_construction() {
10 | // Query builders should be usable as soon as it's constructed - it should be able to execute a query with some default values
11 | String searchTerm = 'test';
12 | ISObjectQueryBuilder opportunityQueryBuilder = new SObjectQueryBuilder(Schema.Opportunity.SObjectType);
13 |
14 | ISearchQueryBuilder searchQueryBuilder = new SearchQueryBuilder(searchTerm, new List{opportunityQueryBuilder});
15 |
16 | Test.startTest();
17 |
18 | List> results = (List>)searchQueryBuilder.getSearchResults();
19 |
20 | Test.stopTest();
21 | }
22 |
23 | @isTest
24 | static void it_should_cache_results() {
25 | String searchTerm = 'test';
26 | ISObjectQueryBuilder opportunityQueryBuilder = new SObjectQueryBuilder(Schema.Opportunity.SObjectType);
27 |
28 | ISearchQueryBuilder searchQueryBuilder = new SearchQueryBuilder(searchTerm, new List{opportunityQueryBuilder});
29 | searchQueryBuilder.cacheResults();
30 |
31 | Test.startTest();
32 |
33 | System.assertEquals(0, Limits.getSoslQueries());
34 | for(Integer i = 0; i < 10; i++) {
35 | System.debug(searchQueryBuilder.getSearchResults());
36 | }
37 |
38 | System.assertEquals(1, Limits.getSoslQueries());
39 |
40 | Test.stopTest();
41 | }
42 |
43 | @isTest
44 | static void it_should_set_search_group() {
45 | // TODO finish writing tests!
46 | }
47 |
48 | @isTest
49 | static void it_should_add_sobject_query_builder() {
50 | // TODO finish writing tests!
51 | }
52 |
53 | @isTest
54 | static void it_should_get_query() {
55 | // TODO finish writing tests!
56 | }
57 |
58 | @isTest
59 | static void it_should_get_first_query_results() {
60 | // TODO finish writing tests!
61 | }
62 |
63 | @isTest
64 | static void it_should_get_query_results() {
65 | // TODO finish writing tests!
66 | }
67 |
68 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/SObjectFieldDescriber_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class SObjectFieldDescriber_Tests {
7 |
8 | @isTest
9 | static void it_should_return_the_sobject_type() {
10 | Schema.SObjectType expectedSObjectType = Schema.Lead.SObjectType;
11 | Schema.SObjectField sobjectField = Schema.Lead.Id;
12 |
13 | Test.startTest();
14 |
15 | SObjectFieldDescriber sobjectFieldDescriber = new SObjectFieldDescriber(sobjectField);
16 | System.assertEquals(expectedSObjectType, sobjectFieldDescriber.getSObjectType());
17 |
18 | Test.stopTest();
19 | }
20 |
21 | @isTest
22 | static void it_should_validate_the_expected_sobject_type() {
23 | Schema.SObjectType expectedSObjectType = Schema.Lead.SObjectType;
24 | Schema.SObjectField sobjectField = Schema.Lead.Id;
25 |
26 | Test.startTest();
27 |
28 | SObjectFieldDescriber sobjectFieldDescriber = new SObjectFieldDescriber(sobjectField);
29 | System.assert(sobjectFieldDescriber.validateSObjectType(expectedSObjectType));
30 |
31 | Test.stopTest();
32 | }
33 |
34 | @isTest
35 | static void it_should_return_the_full_field_name() {
36 | Schema.SObjectType expectedSObjectType = Schema.Lead.SObjectType;
37 | Schema.SObjectField sobjectField = Schema.Lead.Id;
38 | String expectedFullFieldName = String.valueOf(expectedSObjectType) + '.' + String.valueOf(sobjectField);
39 |
40 | Test.startTest();
41 |
42 | SObjectFieldDescriber sobjectFieldDescriber = new SObjectFieldDescriber(sobjectField);
43 | System.assertEquals(expectedFullFieldName, sobjectFieldDescriber.getFullFieldName());
44 |
45 | Test.stopTest();
46 | }
47 |
48 | @isTest
49 | static void it_should_return_the_parent_field_sobject_type() {
50 | Schema.SObjectField sobjectField = Schema.Lead.ConvertedAccountId;
51 | Schema.SObjectType expectedParentSObjectType = Schema.Account.SObjectType;
52 |
53 | Test.startTest();
54 |
55 | SObjectFieldDescriber sobjectFieldDescriber = new SObjectFieldDescriber(sobjectField);
56 | System.assertEquals(expectedParentSObjectType, sobjectFieldDescriber.getParentSObjectType());
57 |
58 | Test.stopTest();
59 | }
60 |
61 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/SObjectRecordTypes.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Record Types
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public abstract class SObjectRecordTypes extends NebulaCore implements ISObjectRecordTypes {
14 |
15 | private String sobjectName;
16 |
17 | public SObjectRecordTypes() {
18 | this.currentModule = NebulaCore.Module.RECORD_TYPES;
19 |
20 | this.sobjectName = this.getSObjectType().getDescribe().getName();
21 | }
22 |
23 | public abstract Schema.SObjectType getSObjectType();
24 |
25 | public Map getAllById() {
26 | return new Map(getRecordTypes());
27 | }
28 |
29 | public Map getAllByDeveloperName() {
30 | Map allRecordTypesByDeveloperName = new Map();
31 | for(RecordType recordType : this.getAllById().values()) {
32 | if(recordType.SObjectType != this.sobjectName) continue;
33 |
34 | allRecordTypesByDeveloperName.put(recordType.DeveloperName, recordType);
35 | }
36 |
37 | return allRecordTypesByDeveloperName;
38 | }
39 |
40 | private List getRecordTypes() {
41 | Schema.SObjectType recordTypeSObjectType = Schema.SObjectType.RecordType.getSObjectType();
42 | ISObjectQueryBuilder query = new SObjectQueryBuilder(recordTypeSObjectType).orderBy(new QueryField(Schema.RecordType.DeveloperName));
43 |
44 | // If we don't have the SObject cached, then we need to query
45 | if(NebulaSettings.RecordTypesSettings.LazyLoad__c) {
46 | query.filterBy(new QueryFilter().filterByField(new QueryField(Schema.RecordType.SObjectType), QueryOperator.EQUALS, this.sobjectName));
47 | Logger.addEntry(this, 'NebulaSettings.RecordTypesSettings.LazyLoad__c=' + NebulaSettings.RecordTypesSettings.LazyLoad__c);
48 | Logger.addEntry(this, 'this.sobjectName=' + this.sobjectName);
49 | }
50 |
51 | if(!NebulaSettings.RecordTypesSettings.IncludeManagedRecordTypes__c) {
52 | query.filterBy(new QueryFilter().filterByField(new QueryField(Schema.RecordType.NamespacePrefix), QueryOperator.EQUALS, null));
53 | }
54 |
55 | Logger.addEntry(this, 'Loading SObjectRecordTypes for=' + this.getSObjectType());
56 |
57 | return (List)query.cacheResults().getQueryResults();
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/AggregateResultQueryBuilder_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class AggregateResultQueryBuilder_Tests {
7 |
8 |
9 | @isTest
10 | static void it_should_be_usable_after_construction() {
11 | // Query builders should be usable as soon as it's constructed - it should be able to execute a query with some default values
12 | IAggregateResultQueryBuilder aggregateQueryBuilder = new AggregateResultQueryBuilder(Schema.Opportunity.SObjectType);
13 |
14 | Test.startTest();
15 |
16 | List results = (List)aggregateQueryBuilder.getQueryResults();
17 |
18 | Test.stopTest();
19 | }
20 |
21 | @isTest
22 | static void it_should_cache_results() {
23 | IAggregateResultQueryBuilder aggregateResultQueryBuilder = new AggregateResultQueryBuilder(Schema.Opportunity.SObjectType);
24 | aggregateResultQueryBuilder.cacheResults();
25 |
26 | Test.startTest();
27 |
28 | System.assertEquals(0, Limits.getQueries());
29 | for(Integer i = 0; i < 10; i++) {
30 | System.debug(aggregateResultQueryBuilder.getQueryResults());
31 | }
32 |
33 | System.assertEquals(1, Limits.getQueries());
34 |
35 | Test.stopTest();
36 | }
37 |
38 | @isTest
39 | static void it_should_build_a_ridiculous_query_string() {
40 | String expectedString = 'SELECT Type,\nAVG(Amount) AVG__Amount, COUNT(AccountId) COUNT__AccountId, '
41 | + 'COUNT_DISTINCT(OwnerId) COUNT_DISTINCT__OwnerId, MAX(CreatedDate) MAX__CreatedDate, MIN(CreatedDate) MIN__CreatedDate'
42 | + '\nFROM Opportunity'
43 | + '\nGROUP BY Type';
44 |
45 | IAggregateResultQueryBuilder aggregateResultQueryBuilder = new AggregateResultQueryBuilder(Schema.Opportunity.SObjectType)
46 | .max(new QueryField(Schema.Opportunity.CreatedDate))
47 | .avg(new QueryField(Schema.Opportunity.Amount))
48 | .countDistinct(new QueryField(Schema.Opportunity.OwnerId))
49 | .min(new QueryField(Schema.Opportunity.CreatedDate))
50 | .groupBy(new QueryField(Schema.Opportunity.Type))
51 | .count(new QueryField(Schema.Opportunity.AccountId));
52 | String returnedQueryString = aggregateResultQueryBuilder.getQuery();
53 |
54 | System.assertEquals(expectedString, returnedQueryString);
55 |
56 | // Verify that the query can be executed
57 | Database.query(returnedQueryString);
58 | }
59 |
60 |
61 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/objects/NebulaLog__c/NebulaLog__c.object-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Accept
5 | Default
6 |
7 |
8 | CancelEdit
9 | Default
10 |
11 |
12 | Clone
13 | Default
14 |
15 |
16 | Delete
17 | Default
18 |
19 |
20 | Edit
21 | Default
22 |
23 |
24 | List
25 | Default
26 |
27 |
28 | New
29 | Default
30 |
31 |
32 | SaveEdit
33 | Default
34 |
35 |
36 | Tab
37 | Default
38 |
39 |
40 | View
41 | Default
42 |
43 | true
44 | SYSTEM
45 | Deployed
46 | Stores log records, as well as attachments, that are generated by the Nebula framework.
47 | false
48 | true
49 | false
50 | true
51 | true
52 | true
53 | true
54 | true
55 |
56 |
57 | Log-{00000}
58 |
59 | false
60 | AutoNumber
61 |
62 | Nebula Logs
63 |
64 | InitialClass__c
65 | TransactionId__c
66 | CREATEDBY_USER
67 | CREATED_DATE
68 |
69 | ReadWrite
70 | Public
71 |
72 |
--------------------------------------------------------------------------------
/nebula-app-framework/tests/dml-management/classes/DMLMock_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class DMLMock_Tests {
7 |
8 | static IDML dmlRepo = new DMLMock.Base();
9 | static Schema.Contact con = createContact();
10 |
11 | @isTest
12 | static void it_should_fake_dml_insert() {
13 | Test.startTest();
14 | dmlRepo.insertRecords(con);
15 | Test.stopTest();
16 |
17 | System.assert(TestingUtils.insertedRecords.size() > 0);
18 | }
19 |
20 | @isTest
21 | static void it_should_fake_dml_update() {
22 | Test.startTest();
23 | dmlRepo.updateRecords(con);
24 | Test.stopTest();
25 |
26 | System.assert(!TestingUtils.updatedRecords.isEmpty());
27 | }
28 |
29 | @isTest
30 | static void it_should_fake_dml_upsert() {
31 | Test.startTest();
32 | dmlRepo.upsertRecords(con);
33 | Test.stopTest();
34 |
35 | System.assert(!TestingUtils.upsertedRecords.isEmpty());
36 | }
37 |
38 | @isTest
39 | static void it_should_fake_dml_delete() {
40 | Test.startTest();
41 | dmlRepo.deleteRecords(con);
42 | Test.stopTest();
43 |
44 | System.assert(!TestingUtils.deletedRecords.isEmpty());
45 | }
46 |
47 | @isTest
48 | static void it_should_fake_dml_hard_delete() {
49 | Test.startTest();
50 | dmlRepo.hardDeleteRecords(con);
51 | Test.stopTest();
52 |
53 | System.assert(!TestingUtils.deletedRecords.isEmpty());
54 | }
55 |
56 | @isTest
57 | static void it_should_fake_dml_undelete() {
58 | Test.startTest();
59 | dmlRepo.undeleteRecords(con);
60 | Test.stopTest();
61 |
62 | System.assert(!TestingUtils.undeletedRecords.isEmpty());
63 | }
64 |
65 | @isTest
66 | static void it_should_mock_updating_read_only_fields_when_updating_data() {
67 | Schema.Lead l = new Schema.Lead();
68 | l = (Lead)TestingUtils.setReadOnlyField(l, Schema.Lead.IsConverted, true);
69 |
70 | Test.startTest();
71 | dmlRepo.updateRecords(l);
72 | Test.stoptest();
73 |
74 | SObject record = TestingUtils.updatedRecords[0];
75 | System.assert(record instanceof Schema.Lead);
76 | System.assert(record.get('IsConverted') != null);
77 | }
78 |
79 | private static Contact createContact() {
80 | con = new Contact();
81 | con.Email = 'rightHandMan@hamilton.com';
82 | con.FirstName = 'George';
83 | con.LastName = 'Washington';
84 | con.LeadSource = 'Web';
85 |
86 | return con;
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/layouts/NebulaLog__c-Log Layout.layout-meta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Submit
4 |
5 | false
6 | false
7 | true
8 |
9 |
10 |
11 | Readonly
12 | Name
13 |
14 |
15 | Required
16 | TransactionId__c
17 |
18 |
19 |
20 |
21 | Edit
22 | InitialClass__c
23 |
24 |
25 |
26 |
27 |
28 | true
29 | true
30 | true
31 |
32 |
33 |
34 |
35 |
36 | false
37 | true
38 | true
39 |
40 |
41 |
42 | Readonly
43 | CreatedById
44 |
45 |
46 |
47 |
48 | Readonly
49 | LastModifiedById
50 |
51 |
52 |
53 |
54 |
55 | true
56 | false
57 | true
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | RelatedNoteList
66 |
67 |
68 | RelatedEntityHistoryList
69 |
70 | false
71 | false
72 | false
73 | false
74 | false
75 |
76 | 00h0Y000001YebH
77 | 4
78 | 0
79 | Default
80 |
81 |
82 |
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/IAggregateResultQueryBuilder.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public interface IAggregateResultQueryBuilder {
14 |
15 | IAggregateResultQueryBuilder cacheResults();
16 |
17 | // Group By methods
18 | IAggregateResultQueryBuilder groupBy(IQueryField groupByQueryField);
19 | IAggregateResultQueryBuilder groupBy(List groupByQueryFields);
20 | IAggregateResultQueryBuilder groupBy(Schema.FieldSet fieldSet);
21 | IAggregateResultQueryBuilder groupBy(QueryDate queryDate);
22 | // TODO add support for other features, like 'having count(id) > 1', etc support
23 | // https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_groupby.htm
24 | // TODO need to research 'GROUP BY CUBE' & 'GROUPING' more https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_groupby_cube.htm
25 |
26 | // Aggregate functions
27 | IAggregateResultQueryBuilder avg(IQueryField queryField);
28 | IAggregateResultQueryBuilder avg(IQueryField queryField, String fieldAlias);
29 | IAggregateResultQueryBuilder count(IQueryField queryField);
30 | IAggregateResultQueryBuilder count(IQueryField queryField, String fieldAlias);
31 | IAggregateResultQueryBuilder countDistinct(IQueryField queryField);
32 | IAggregateResultQueryBuilder countDistinct(IQueryField queryField, String fieldAlias);
33 | IAggregateResultQueryBuilder max(IQueryField queryField);
34 | IAggregateResultQueryBuilder max(IQueryField queryField, String fieldAlias);
35 | IAggregateResultQueryBuilder min(IQueryField queryField);
36 | IAggregateResultQueryBuilder min(IQueryField queryField, String fieldAlias);
37 | IAggregateResultQueryBuilder sum(IQueryField queryField);
38 | IAggregateResultQueryBuilder sum(IQueryField queryField, String fieldAlias);
39 |
40 | // Filter methods
41 | IAggregateResultQueryBuilder filterBy(IQueryFilter queryFilter);
42 | IAggregateResultQueryBuilder filterBy(List queryFilters);
43 |
44 | // Order By methods
45 | IAggregateResultQueryBuilder orderBy(IQueryField orderByQueryField);
46 | IAggregateResultQueryBuilder orderBy(IQueryField orderByQueryField, QuerySortOrder sortOrder);
47 | IAggregateResultQueryBuilder orderBy(IQueryField orderByQueryField, QuerySortOrder sortOrder, QueryNullSortOrder nullsSortOrder);
48 |
49 | // Additional query option methods
50 | IAggregateResultQueryBuilder limitCount(Integer limitCount);
51 |
52 | // Query string methods
53 | String getQuery();
54 |
55 | // Query execution methods
56 | AggregateResult getFirstQueryResult();
57 | List getQueryResults();
58 |
59 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/SObjectFieldDescriber.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Metadata
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public without sharing class SObjectFieldDescriber {
14 | // We would love for Schema.SObjectField to have a way to return the SObject Type
15 | // Sadly, it doesn't, so we have this class to fill the void.
16 | // If a proper method is ever added to Apex to get the field's SObject Type,
17 | // then we should consider removing this class.
18 |
19 | private static Map sobjectFieldHashCodeToSObjectTypeMap;
20 |
21 | private Schema.SObjectField sobjectField;
22 | private Schema.SObjectType sobjectType;
23 |
24 | public SObjectFieldDescriber(Schema.SObjectField sobjectField) {
25 | this.cacheSObjectTypeFieldHashCodes();
26 |
27 | this.sobjectField = sobjectField;
28 | this.setSObjectType();
29 | }
30 |
31 | public String getFieldName() {
32 | return this.sobjectField.getDescribe().getName();
33 | }
34 |
35 | public String getFullFieldName() {
36 | return this.sobjectType + '.' + this.getFieldName();
37 | }
38 |
39 | public Schema.SObjectType getSObjectType() {
40 | return this.sobjectType;
41 | }
42 |
43 | public Schema.SObjectType getParentSObjectType() {
44 | Schema.DescribeFieldResult fieldDescribe = this.SObjectField.getDescribe();
45 |
46 | Schema.SObjectType parentSObjectType;
47 | if(!fieldDescribe.isNamePointing() && !fieldDescribe.getReferenceTo().isEmpty()) parentSObjectType = fieldDescribe.getReferenceTo()[0];
48 |
49 | return parentSObjectType;
50 | }
51 |
52 | public Boolean validateSObjectType(Schema.SObjectType expectedSObjectType) {
53 | return this.SObjectType == expectedSObjectType;
54 | }
55 |
56 | private void setSObjectType() {
57 | Integer sobjectFieldHashCode = this.getHashCode(this.sobjectField);
58 | this.SObjectType = sobjectFieldHashCodeToSObjectTypeMap.get(sobjectFieldHashCode);
59 | }
60 |
61 | private void cacheSObjectTypeFieldHashCodes() {
62 | // Describe calls are "free" but still add CPU time, so let's cache them
63 | if(sobjectFieldHashCodeToSObjectTypeMap != null) return;
64 |
65 | sobjectFieldHashCodeToSObjectTypeMap = new Map();
66 |
67 | // Build a map of hash codes for each fieldDescribe taken from Schema Global Describe
68 | Map globalDescribe = Schema.getGlobalDescribe();
69 | for(String sobjTypeName : globalDescribe.keySet()) {
70 | SObjectType sobjType = globalDescribe.get(sobjTypeName);
71 |
72 | for(Schema.SObjectField sobjField : sobjType.getDescribe().fields.getMap().values()) {
73 | Integer sobjFieldHashCode = getHashCode(sobjField);
74 |
75 | sobjectFieldHashCodeToSObjectTypeMap.put(sobjFieldHashCode, sobjType);
76 | }
77 | }
78 | }
79 |
80 | private Integer getHashCode(Schema.SObjectField sobjField) {
81 | return ((Object)sobjField).hashCode();
82 | }
83 |
84 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/utilities/classes/NebulaSettings.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Configuration
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public without sharing class NebulaSettings {
14 |
15 | /**
16 | * @description TODO
17 | * returns true if it's a sandbox
18 | */
19 | public static NebulaLoggerSettings__c LoggerSettings {get; private set;}
20 | public static NebulaRecordTypesSettings__c RecordTypesSettings {get; private set;}
21 | public static NebulaSObjectQueryBuilderSettings__c SObjectQueryBuilderSettings {get; private set;}
22 | public static NebulaTriggerHandlerSettings__c TriggerHandlerSettings {get; private set;}
23 |
24 | static {
25 | loadCustomSettings();
26 | }
27 |
28 | public static void resetAllSettingsToDefaults() {
29 | deleteExistingCustomSettings();
30 | createCustomSettings();
31 | }
32 |
33 | private static void loadCustomSettings() {
34 | loadLoggerSettings();
35 | loadRecordTypesSettings();
36 | loadSObjectQueryBuilderSettings();
37 | loadTriggerHandlerSettings();
38 | }
39 |
40 | private static void deleteExistingCustomSettings() {
41 | delete [SELECT Id FROM NebulaLoggerSettings__c];
42 | delete [SELECT Id FROM NebulaRecordTypesSettings__c];
43 | delete [SELECT Id FROM NebulaSObjectQueryBuilderSettings__c];
44 | delete [SELECT Id FROM NebulaTriggerHandlerSettings__c];
45 | }
46 |
47 | private static void createCustomSettings() {
48 | upsert NebulaLoggerSettings__c.getOrgDefaults();
49 | upsert NebulaRecordTypesSettings__c.getOrgDefaults();
50 | upsert NebulaSObjectQueryBuilderSettings__c.getOrgDefaults();
51 | upsert NebulaTriggerHandlerSettings__c.getOrgDefaults();
52 | }
53 |
54 | private static void loadLoggerSettings() {
55 | loggerSettings = NebulaLoggerSettings__c.getInstance();
56 |
57 | if(loggerSettings.Id == null) {
58 | upsert NebulaLoggerSettings__c.getOrgDefaults();
59 | loggerSettings = NebulaLoggerSettings__c.getInstance();
60 | }
61 | }
62 |
63 | private static void loadRecordTypesSettings() {
64 | recordTypesSettings = NebulaRecordTypesSettings__c.getInstance();
65 |
66 | if(recordTypesSettings.Id == null) {
67 | upsert NebulaRecordTypesSettings__c.getOrgDefaults();
68 | recordTypesSettings = NebulaRecordTypesSettings__c.getInstance();
69 | }
70 | }
71 |
72 | private static void loadSObjectQueryBuilderSettings() {
73 | sobjectQueryBuilderSettings = NebulaSObjectQueryBuilderSettings__c.getInstance();
74 |
75 | if(sobjectQueryBuilderSettings.Id == null) {
76 | upsert NebulaSObjectQueryBuilderSettings__c.getOrgDefaults();
77 | sobjectQueryBuilderSettings = NebulaSObjectQueryBuilderSettings__c.getInstance();
78 | }
79 | }
80 |
81 | private static void loadTriggerHandlerSettings() {
82 | triggerHandlerSettings = NebulaTriggerHandlerSettings__c.getInstance();
83 |
84 | if(triggerHandlerSettings.Id == null) {
85 | upsert NebulaTriggerHandlerSettings__c.getOrgDefaults();
86 | triggerHandlerSettings = NebulaTriggerHandlerSettings__c.getInstance();
87 | }
88 | }
89 |
90 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/sobject-repositories/classes/SObjectRepository.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Repository
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public abstract class SObjectRepository extends DML implements ISObjectRepository, IDML {
14 |
15 | private List sobjectFieldList;
16 | private Map sobjectFieldMap;
17 | private QueryField idQueryField;
18 |
19 | public SObjectRepository() {
20 | this.currentModule = NebulaCore.Module.REPOSITORY;
21 |
22 | this.sobjectFieldMap = this.getSObjectType().getDescribe().fields.getMap();
23 | this.idQueryField = new QueryField(this.getField('Id'));
24 | }
25 |
26 | public abstract Schema.SObjectType getSObjectType();
27 |
28 | // SOQL
29 | public virtual SObject getById(Id recordId) {
30 | return new SObjectQueryBuilder(this.getSObjectType())
31 | .filterBy(new QueryFilter().filterByField(this.idQueryField, QueryOperator.EQUALS, recordId))
32 | .filterBy(new QueryFilter().filterByField(this.idQueryField, QueryOperator.EQUALS, recordId))
33 | .getFirstQueryResult();
34 | }
35 |
36 | public virtual List getById(List recordIds) {
37 | return new SObjectQueryBuilder(this.getSObjectType())
38 | .filterBy(new QueryFilter().filterByField(this.idQueryField, QueryOperator.IS_IN, recordIds))
39 | .getQueryResults();
40 | }
41 |
42 | public virtual List get(IQueryFilter queryFilter) {
43 | return this.get(new List{queryFilter});
44 | }
45 |
46 | public virtual List get(List queryFilters) {
47 | return new SObjectQueryBuilder(this.getSObjectType())
48 | .filterBy(queryFilters)
49 | .getQueryResults();
50 | }
51 |
52 | public virtual List getByIdAndQueryFilters(Set idSet, List queryFilters) {
53 | return this.getByIdAndQueryFilters(new List(idSet), queryFilters);
54 | }
55 |
56 | public virtual List getByIdAndQueryFilters(List idList, List queryFilters) {
57 | return new SObjectQueryBuilder(this.getSObjectType())
58 | .filterBy(new QueryFilter().filterByField(this.idQueryField, QueryOperator.IS_IN, idList))
59 | .filterBy(queryFilters)
60 | .getQueryResults();
61 | }
62 |
63 | // SOSL
64 | public virtual List getSearchResults(String searchTerm) {
65 | return this.getSearchResults(searchTerm, QuerySearchGroup.ALL_FIELDS, null);
66 | }
67 |
68 | public virtual List getSearchResults(String searchTerm, QuerySearchGroup searchGroup) {
69 | return this.getSearchResults(searchTerm, searchGroup, null);
70 | }
71 |
72 | public virtual List getSearchResults(String searchTerm, QuerySearchGroup searchGroup, List queryFilters) {
73 | return new SearchQueryBuilder(searchTerm, new SObjectQueryBuilder(this.getSObjectType())
74 | .filterBy(queryFilters))
75 | .inQuerySearchGroup(searchGroup)
76 | .getFirstSearchResult();
77 | }
78 |
79 | private Schema.SObjectField getField(String fieldName) {
80 | return this.sobjectFieldMap.get(fieldName);
81 | }
82 |
83 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/SearchQueryBuilder.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description A builder class that generates dynamic SOSL queries & returns a list of SObjects or list of a list of SObjects
11 | *
12 | */
13 | public class SearchQueryBuilder extends QueryBuilder implements ISearchQueryBuilder {
14 |
15 | private String searchTerm;
16 | private QuerySearchGroup searchGroup;
17 | private List sobjectQueryBuilders;
18 | private List sobjectQueries;
19 | private Boolean withHighlight;
20 | private Boolean withSpellCorrection;
21 |
22 | public SearchQueryBuilder(String searchTerm, ISObjectQueryBuilder sobjectQueryBuilder) {
23 | this(searchTerm, new List{sobjectQueryBuilder});
24 | }
25 |
26 | public SearchQueryBuilder(String searchTerm, List sobjectQueryBuilders) {
27 | this.searchTerm = searchTerm;
28 | this.sobjectQueryBuilders = sobjectQueryBuilders;
29 |
30 | this.searchGroup = QuerySearchGroup.ALL_FIELDS;
31 | this.sobjectQueries = new List();
32 |
33 | this.parseSObjectQueryBuilders();
34 | }
35 |
36 | public ISearchQueryBuilder cacheResults() {
37 | super.doCacheResults();
38 | return this;
39 | }
40 |
41 | public ISearchQueryBuilder inQuerySearchGroup(QuerySearchGroup searchGroup) {
42 | this.searchGroup = searchGroup;
43 | return this;
44 | }
45 |
46 | public ISearchQueryBuilder withHighlight(Boolean withHighlight) {
47 | this.withHighlight = withHighlight;
48 | return this;
49 | }
50 |
51 | public ISearchQueryBuilder withSpellCorrection(Boolean withSpellCorrection) {
52 | this.withHighlight = withSpellCorrection;
53 | return this;
54 | }
55 |
56 | public String getQuery() {
57 | String query = 'FIND ' + new QueryArgumentFormatter(this.searchTerm.toLowerCase()).getValue()
58 | + '\nIN ' + this.searchGroup.name().replace('_', ' ')
59 | + '\nRETURNING ' + this.getSObjectQueriesString()
60 | + this.getWithHighlightString()
61 | + this.getWithSpellCorrectionString();
62 |
63 | return query;
64 | }
65 |
66 | public List getFirstSearchResult() {
67 | return this.getSearchResults()[0];
68 | }
69 |
70 | public List> getSearchResults() {
71 | return super.doGetSearchResults(this.getQuery());
72 | }
73 |
74 | private ISearchQueryBuilder parseSObjectQueryBuilders() {
75 | for(ISObjectQueryBuilder sobjectQueryBuilder : this.sobjectQueryBuilders) {
76 | this.sobjectQueries.add(sobjectQueryBuilder.getSearchQuery());
77 | }
78 | return this;
79 | }
80 |
81 | private String getSObjectQueriesString() {
82 | this.sobjectQueries.sort();
83 | return String.join(this.sobjectQueries, ', ');
84 | }
85 |
86 | private String getWithHighlightString() {
87 | return (this.withHighlight == null || !this.withHighlight) ? '' : '\nWITH HIGHLIGHT';
88 | }
89 |
90 | private String getWithSpellCorrectionString() {
91 | return this.withSpellCorrection == null ? '' : '\nWITH SPELL_CORRECTION = ' + this.withSpellCorrection;
92 | }
93 |
94 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/utilities/classes/NebulaSettings_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class NebulaSettings_Tests {
7 |
8 | @isTest
9 | static void it_should_return_record_types_settings() {
10 | List existingSettings = [SELECT Id FROM NebulaRecordTypesSettings__c];
11 | System.assert(existingSettings.isEmpty());
12 |
13 | Test.startTest();
14 | System.assertNotEquals(null, NebulaSettings.RecordTypesSettings);
15 | Test.stopTest();
16 | }
17 |
18 | @isTest
19 | static void it_should_return_logger_settings() {
20 | List existingSettings = [SELECT Id FROM NebulaLoggerSettings__c];
21 | System.assert(existingSettings.isEmpty());
22 |
23 | Test.startTest();
24 | System.assertNotEquals(null, NebulaSettings.LoggerSettings);
25 | Test.stopTest();
26 | }
27 |
28 | @isTest
29 | static void it_should_return_SObjectQueryBuilder_settings() {
30 | List existingSettings = [SELECT Id FROM NebulaSObjectQueryBuilderSettings__c];
31 | System.assert(existingSettings.isEmpty());
32 |
33 | Test.startTest();
34 | System.assertNotEquals(null, NebulaSettings.SObjectQueryBuilderSettings);
35 | Test.stopTest();
36 | }
37 |
38 | @isTest
39 | static void it_should_return_trigger_handler_settings() {
40 | List existingSettings = [SELECT Id FROM NebulaTriggerHandlerSettings__c];
41 | System.assert(existingSettings.isEmpty());
42 |
43 | Test.startTest();
44 | System.assertNotEquals(null, NebulaSettings.TriggerHandlerSettings);
45 | Test.stopTest();
46 | }
47 |
48 | @isTest
49 | static void it_should_reset_all_settings_to_defaults() {
50 | NebulaLoggerSettings__c nebulaLoggerSettings = NebulaLoggerSettings__c.getInstance();
51 | upsert nebulaLoggerSettings;
52 | Id originalLoggerSettingsId = NebulaLoggerSettings__c.getInstance().Id;
53 |
54 | NebulaRecordTypesSettings__c nebulaRecordTypesSettings = NebulaRecordTypesSettings__c.getInstance();
55 | upsert nebulaRecordTypesSettings;
56 | Id originalRecordTypesSettingsId = NebulaRecordTypesSettings__c.getInstance().Id;
57 |
58 | NebulaSObjectQueryBuilderSettings__c nebulaSObjectQueryBuilderSettings = NebulaSObjectQueryBuilderSettings__c.getInstance();
59 | upsert nebulaSObjectQueryBuilderSettings;
60 | Id originalSObjectQueryBuilderSettingsId = NebulaSObjectQueryBuilderSettings__c.getInstance().Id;
61 |
62 | NebulaTriggerHandlerSettings__c nebulaTriggerHandlerSettings = NebulaTriggerHandlerSettings__c.getInstance();
63 | upsert nebulaTriggerHandlerSettings;
64 | Id originalTriggerHandlerSettingsId = NebulaTriggerHandlerSettings__c.getInstance().Id;
65 |
66 | Test.startTest();
67 | NebulaSettings.resetAllSettingsToDefaults();
68 | Test.stopTest();
69 |
70 | System.assertNotEquals(originalLoggerSettingsId, NebulaLoggerSettings__c.getInstance().Id);
71 | System.assertNotEquals(originalRecordTypesSettingsId, NebulaRecordTypesSettings__c.getInstance().Id);
72 | System.assertNotEquals(originalSObjectQueryBuilderSettingsId, NebulaSObjectQueryBuilderSettings__c.getInstance().Id);
73 | System.assertNotEquals(originalTriggerHandlerSettingsId, NebulaTriggerHandlerSettings__c.getInstance().Id);
74 | }
75 |
76 | }
--------------------------------------------------------------------------------
/nebula-app-framework/tests/query-and-search/classes/QueryDate_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class QueryDate_Tests {
7 |
8 | @isTest
9 | static void it_should_return_sobject_type() {
10 | QueryDate dt = QueryDate.CALENDAR_MONTH(Schema.User.CreatedDate);
11 | System.assertEquals(Schema.User.SObjectType, dt.getSObjectType());
12 | }
13 |
14 | @isTest
15 | static void it_should_return_calendar_month_string() {
16 | QueryDate dt = QueryDate.CALENDAR_MONTH(Schema.User.CreatedDate);
17 | System.assertEquals('CALENDAR_MONTH(CreatedDate)', dt.getValue());
18 | }
19 |
20 | @isTest
21 | static void it_should_return_calendar_quarter_string() {
22 | QueryDate dt = QueryDate.CALENDAR_QUARTER(Schema.User.CreatedDate);
23 | System.assertEquals('CALENDAR_QUARTER(CreatedDate)', dt.getValue());
24 | }
25 |
26 | @isTest
27 | static void it_should_return_calendar_year_string() {
28 | QueryDate dt = QueryDate.CALENDAR_YEAR(Schema.User.CreatedDate);
29 | System.assertEquals('CALENDAR_YEAR(CreatedDate)', dt.getValue());
30 | }
31 |
32 | @isTest
33 | static void it_should_return_day_in_month_string() {
34 | QueryDate dt = QueryDate.DAY_IN_MONTH(Schema.User.CreatedDate);
35 | System.assertEquals('DAY_IN_MONTH(CreatedDate)', dt.getValue());
36 | }
37 |
38 | @isTest
39 | static void it_should_return_day_in_week_string() {
40 | QueryDate dt = QueryDate.DAY_IN_WEEK(Schema.User.CreatedDate);
41 | System.assertEquals('DAY_IN_WEEK(CreatedDate)', dt.getValue());
42 | }
43 |
44 | @isTest
45 | static void it_should_return_day_in_year_string() {
46 | QueryDate dt = QueryDate.DAY_IN_YEAR(Schema.User.CreatedDate);
47 | System.assertEquals('DAY_IN_YEAR(CreatedDate)', dt.getValue());
48 | }
49 |
50 | @isTest
51 | static void it_should_return_day_only_string() {
52 | QueryDate dt = QueryDate.DAY_ONLY(Schema.User.CreatedDate);
53 | System.assertEquals('DAY_ONLY(CreatedDate)', dt.getValue());
54 | }
55 |
56 | @isTest
57 | static void it_should_return_fiscal_month_string() {
58 | QueryDate dt = QueryDate.FISCAL_MONTH(Schema.User.CreatedDate);
59 | System.assertEquals('FISCAL_MONTH(CreatedDate)', dt.getValue());
60 | }
61 |
62 | @isTest
63 | static void it_should_return_fiscal_quarter_string() {
64 | QueryDate dt = QueryDate.FISCAL_QUARTER(Schema.User.CreatedDate);
65 | System.assertEquals('FISCAL_QUARTER(CreatedDate)', dt.getValue());
66 | }
67 |
68 | @isTest
69 | static void it_should_return_fiscal_year_string() {
70 | QueryDate dt = QueryDate.FISCAL_YEAR(Schema.User.CreatedDate);
71 | System.assertEquals('FISCAL_YEAR(CreatedDate)', dt.getValue());
72 | }
73 |
74 | @isTest
75 | static void it_should_return_hour_in_day_string() {
76 | QueryDate dt = QueryDate.HOUR_IN_DAY(Schema.User.CreatedDate);
77 | System.assertEquals('HOUR_IN_DAY(CreatedDate)', dt.getValue());
78 | }
79 |
80 | @isTest
81 | static void it_should_return_week_in_month_string() {
82 | QueryDate dt = QueryDate.WEEK_IN_MONTH(Schema.User.CreatedDate);
83 | System.assertEquals('WEEK_IN_MONTH(CreatedDate)', dt.getValue());
84 | }
85 |
86 | @isTest
87 | static void it_should_return_week_in_year_string() {
88 | QueryDate dt = QueryDate.WEEK_IN_YEAR(Schema.User.CreatedDate);
89 | System.assertEquals('WEEK_IN_YEAR(CreatedDate)', dt.getValue());
90 | }
91 |
92 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/dml-management/classes/DML.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Repository
9 | *
10 | * @description Provides methods with default behavior for DML actions (insert, upsert, etc)
11 | *
12 | */
13 | public abstract class DML extends NebulaCore implements IDML {
14 |
15 | public virtual List insertRecords(SObject record) {
16 | return this.insertRecords(new List{record});
17 | }
18 |
19 | public virtual List insertRecords(List records) {
20 | return Database.insert(records);
21 | }
22 |
23 | public virtual List updateRecords(SObject record) {
24 | return this.updateRecords(new List{record});
25 | }
26 |
27 | public virtual List updateRecords(List records) {
28 | return Database.update(records);
29 | }
30 |
31 | public virtual List upsertRecords(SObject record) {
32 | return this.upsertRecords(this.castRecords(record));
33 | }
34 |
35 | public virtual List upsertRecords(List records) {
36 | return Database.upsert(records);
37 | }
38 |
39 | public virtual List undeleteRecords(SObject record) {
40 | return this.undeleteRecords(new List{record});
41 | }
42 |
43 | public virtual List undeleteRecords(List records) {
44 | return Database.undelete(records);
45 | }
46 |
47 | public virtual List deleteRecords(SObject record) {
48 | return this.deleteRecords(new List{record});
49 | }
50 |
51 | public virtual List deleteRecords(List records) {
52 | return Database.delete(records);
53 | }
54 |
55 | public virtual List hardDeleteRecords(SObject record) {
56 | return this.hardDeleteRecords(new List{record});
57 | }
58 |
59 | public virtual List hardDeleteRecords(List records) {
60 | List results = this.deleteRecords(records);
61 | if(!records.isEmpty()) Database.emptyRecycleBin(records);
62 | return results;
63 | }
64 |
65 | // Not all objects will have external ID fields, so these methods are protected (instead of public)
66 | // Any object that needs an upsert by external ID can expose these methods in their repos
67 | protected virtual List upsertRecords(SObject record, Schema.SObjectField externalIdField) {
68 | return this.upsertRecords(this.castRecords(record), externalIdField);
69 | }
70 |
71 | protected virtual List upsertRecords(List records, Schema.SObjectField externalIdField) {
72 | return Database.upsert(records, externalIdField);
73 | }
74 |
75 | private List castRecords(SObject record) {
76 | // Salesforce will only allow upsert calls for SObjects if a declared-type list is passed in.
77 | // This is fine for the bulk method, where we can assume the caller is passing in an explicit list, but for a single record,
78 | // the only way to successfully perform the upsert is to dynamically spin up a list of the SObject's type
79 |
80 | String listType = 'List<' + record.getSObjectType() + '>';
81 | List castRecords = (List)Type.forName(listType).newInstance();
82 | castRecords.add(record);
83 |
84 | return castRecords;
85 | }
86 |
87 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/logger/classes/Logger.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Logging
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public without sharing class Logger {
14 |
15 | private static Id logId;
16 | private static Attachment logAttachment;
17 | @testVisible private static List logMessages;
18 |
19 | static {
20 | Logger.logMessages = Logger.logMessages == null ? new List() : Logger.logMessages;
21 | Logger.logAttachment = Logger.logAttachment == null ? createLogAttachment() : Logger.logAttachment;
22 | }
23 |
24 | public static void addEntry(String message) {
25 | addEntry(null, message);
26 | }
27 |
28 | public static void addEntry(INebulaCore moduleClass, String message) {
29 | Logger.Message logMessage = new Logger.Message(moduleClass, message);
30 | Logger.logMessages.add(logMessage);
31 | }
32 |
33 | public static void saveLogs() {
34 | if(!NebulaSettings.LoggerSettings.EnableLogging__c) return;
35 |
36 | saveTransactionLog();
37 | saveSingleLogFile();
38 | }
39 |
40 | private static void saveTransactionLog() {
41 | if(Logger.logId != null) return;
42 |
43 | NebulaLog__c newLog = new NebulaLog__c(
44 | InitialClass__c = NebulaCore.INITIAL_CLASS,
45 | TransactionId__c = NebulaCore.TRANSACTION_ID
46 | );
47 | insert newLog;
48 | Logger.logId = newLog.Id;
49 | }
50 |
51 | private static void saveSingleLogFile() {
52 | String parsedMessageString =
53 | 'NebulaCore.TRANSACTION_ID: ' + NebulaCore.TRANSACTION_ID
54 | + '\nInitial Class: ' + NebulaCore.INITIAL_CLASS;
55 | String divider = '\n______________________________\n';
56 |
57 | for(Logger.Message logMessage : logMessages) {
58 | parsedMessageString =
59 | parsedMessageString
60 | + divider
61 | + '\nCurrent Module: ' + logMessage.ClassModule
62 | + '\nCurrent Class: ' + logMessage.ClassName
63 | + '\nTimestamp: ' + logMessage.Timestamp.format('yyyy-MM-dd_hh:mm:ss.SS')
64 | + '\n\n' + logMessage.Message;
65 | }
66 |
67 | if(Logger.logAttachment.Id == null) {
68 | Logger.logAttachment.Name = NebulaCore.TRANSACTION_ID;
69 | Logger.logAttachment.ParentId = Logger.logId;
70 | }
71 |
72 | Logger.logAttachment.Body = Blob.valueOf(parsedMessageString);
73 |
74 | upsert Logger.logAttachment;
75 | }
76 |
77 | private static Attachment createLogAttachment() {
78 | Attachment attachment = new Attachment(
79 | ContentType = 'text/plain',
80 | IsPrivate = false,
81 | ParentId = Logger.logId
82 | );
83 |
84 | return attachment;
85 | }
86 |
87 | private class Message {
88 | public NebulaCore.Module ClassModule {get; private set;}
89 | public String ClassName {get; private set;}
90 | public String Message {get; private set;}
91 | public Datetime Timestamp {get; private set;}
92 |
93 | public Message(INebulaCore moduleClass, String message) {
94 | this.ClassModule = moduleClass == null ? null : moduleClass.getClassModule();
95 | this.ClassName = moduleClass == null ? null : moduleClass.getClassName();
96 | this.Message = message;
97 | this.Timestamp = System.now();
98 | }
99 | }
100 |
101 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryDate.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description Used to dynamically generate SOQL & SOSQL date functions.
11 | * "Date functions in SOQL queries allow you to group or filter data by date periods such as day, calendar month, or fiscal year."
12 | * Salesforce docs: developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_date_functions.htm
13 | *
14 | */
15 | public without sharing class QueryDate extends NebulaCore {
16 |
17 | private Schema.SObjectField sobjectField;
18 | private Schema.SObjectType sobjectType;
19 | private String value;
20 |
21 | private QueryDate() {
22 | this.currentModule = NebulaCore.Module.QUERY_BUILDER;
23 | }
24 |
25 | public String getValue() {
26 | return this.value;
27 | }
28 |
29 | public Schema.SObjectType getSObjectType() {
30 | return this.sobjectType;
31 | }
32 |
33 | private QueryDate setValue(Schema.SObjectField sobjectField, String value) {
34 | this.sobjectField = sobjectField;
35 | this.sobjectType = new SObjectFieldDescriber(sobjectField).getSObjectType();
36 | this.value = value;
37 | return this;
38 | }
39 |
40 | public static QueryDate CALENDAR_MONTH(Schema.SObjectField sobjectField) {
41 | return buildQueryDate('CALENDAR_MONTH', sobjectField);
42 | }
43 |
44 | public static QueryDate CALENDAR_QUARTER(Schema.SObjectField sobjectField) {
45 | return buildQueryDate('CALENDAR_QUARTER', sobjectField);
46 | }
47 |
48 | public static QueryDate CALENDAR_YEAR(Schema.SObjectField sobjectField) {
49 | return buildQueryDate('CALENDAR_YEAR', sobjectField);
50 | }
51 |
52 | public static QueryDate DAY_IN_MONTH(Schema.SObjectField sobjectField) {
53 | return buildQueryDate('DAY_IN_MONTH', sobjectField);
54 | }
55 |
56 | public static QueryDate DAY_IN_WEEK(Schema.SObjectField sobjectField) {
57 | return buildQueryDate('DAY_IN_WEEK', sobjectField);
58 | }
59 |
60 | public static QueryDate DAY_IN_YEAR(Schema.SObjectField sobjectField) {
61 | return buildQueryDate('DAY_IN_YEAR', sobjectField);
62 | }
63 |
64 | public static QueryDate DAY_ONLY(Schema.SObjectField sobjectField) {
65 | return buildQueryDate('DAY_ONLY', sobjectField);
66 | }
67 |
68 | public static QueryDate FISCAL_MONTH(Schema.SObjectField sobjectField) {
69 | return buildQueryDate('FISCAL_MONTH', sobjectField);
70 | }
71 |
72 | public static QueryDate FISCAL_QUARTER(Schema.SObjectField sobjectField) {
73 | return buildQueryDate('FISCAL_QUARTER', sobjectField);
74 | }
75 |
76 | public static QueryDate FISCAL_YEAR(Schema.SObjectField sobjectField) {
77 | return buildQueryDate('FISCAL_YEAR', sobjectField);
78 | }
79 |
80 | public static QueryDate HOUR_IN_DAY(Schema.SObjectField sobjectField) {
81 | return buildQueryDate('HOUR_IN_DAY', sobjectField);
82 | }
83 |
84 | public static QueryDate WEEK_IN_MONTH(Schema.SObjectField sobjectField) {
85 | return buildQueryDate('WEEK_IN_MONTH', sobjectField);
86 | }
87 |
88 | public static QueryDate WEEK_IN_YEAR(Schema.SObjectField sobjectField) {
89 | return buildQueryDate('WEEK_IN_YEAR', sobjectField);
90 | }
91 |
92 | private static QueryDate buildQueryDate(String dateOperation, Schema.SObjectField sobjectField) {
93 | String value = dateOperation + '(' + sobjectField.getDescribe().getName() + ')';
94 | return new QueryDate().setValue(sobjectField, value);
95 | }
96 |
97 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nebula Framework for Salesforce Apex
2 | [](https://githubsfdeploy.herokuapp.com)
3 | [](https://opensource.org/licenses/MIT)
4 | [](https://travis-ci.org/jongpie/NebulaFramework)
5 | [](https://codeclimate.com/github/jongpie/NebulaFramework)
6 |
7 | Nebula is a development framework for Salesforce's Apex language on the Force.com platform. It aims to...
8 | 1. Provide a foundation for Apex development, with the flexibility to be easily adapted to meet your implementation needs
9 | 2. Promote the design of scalable, bulkified code
10 | 3. Standardise how your code is written & organised
11 | 4. Overcome some gaps in Apex and the Force.com platform
12 |
13 | ## Features
14 | Nebula focusses on streamlining how you work with SObjects
15 | 1. **SObjectRepository.cls** - this module handles all DML actions & querying needs for an SObject, making the implementation of SObjects much easier & faster
16 | * **QueryBuilder.cls** powers Nebula's querying, allowing you to dynamically build reusable SOQL & SOSL queries
17 | * **SObjectRepositoryMock.cls** can be used in unit tests for test-driven development (TDD) & to drastically reduce the time of your unit tests.
18 | 2. **SObjectTriggerHandler.cls** - this module provides a trigger framework to handle all trigger contexts provided by Salesforce, along with additional features like recursion prevention
19 |
20 | The framework also provides several additional classes to make development easier
21 | 1. **SObjectRecordTypes.cls** - record types are an important feature of the Force.com platform. Unfortunately, Apex has limitations with handling them - record types have a field called DeveloperName that (you guessed it!) should be used by developers... but native Apex describe methods cannot access this field. Nebula tries to overcome this by providing cacheable query results of record types so you can access the DeveloperName.
22 | 2. **Logger.cls** - a flexible logging solution for Apex, leveraged by the framework itself
23 | 3. **Environment.cls** - provides information about the current Salesforce environment
24 | 4. **UUID.cls** - used to reate a randomly-generated unique ID in your code, using the Universally Unique Identifier (UUID) standard
25 |
26 | ## Usage
27 | Nebula uses interfaces, virtual & abstract classes and some Salesforce features (like custom settings) to provide a baseline for your own Apex development. You can deploy the latest version of Nebula to your org and build your implementation on top of it. If you want to customise how Nebula works, most classes & methods can be overridden with your own logic. Ideally, you should minimise any code changes to Nebula's classes so that you can easily upgrade in the future when new versions of Nebula are released.
28 |
29 | Nebula also leverages custom settings to give you control over how the framework works within your Salesforce environment. There are 4 settings
30 | 1. **Logger Settings (API Name: NebulaLoggerSettings__c)**
31 | * Enable or disable logging
32 | 2. **Record Type Settings (API Name: NebulaRecordTypesSettings__c)**
33 | * Choose how record types are cached
34 | * Select if you want to include managed record types
35 | 3. **Repository Settings (API Name: NebulaRepositorySettings__c)**
36 | * Automatically include common fields in your queries, like record ID, audit fields (CreatedById, CreatedDate, etc), Name field (or Subject field, where applicable) and more
37 | 4. **Trigger Handler Settings (API Name: NebulaTriggerHandlerSettings__c)**
38 | * Easily disable all triggers & handlers (great for data migration and other admin tasks),
39 | * Enable or disable recursion prevention
40 |
41 | ## Versioning
42 | Releases are versioned using [Semantic Versioning](http://semver.org/) in the format 'v1.0.2' (MAJOR.MINOR.PATCH):
43 |
44 | - MAJOR version when incompatible API changes are made
45 | - MINOR version new functionality is added in a backwards-compatible manner
46 | - PATCH version when backwards-compatible bug fixes are made
--------------------------------------------------------------------------------
/nebula-app-framework/tests/trigger-handlers/classes/SObjectTriggerHandler_Tests.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 | @isTest
6 | private class SObjectTriggerHandler_Tests {
7 |
8 | private class LeadTriggerHandlerTest extends SObjectTriggerHandler {
9 | public LeadTriggerHandlerTest() {
10 | super(true);
11 | }
12 | public override void executeBeforeInsert(List newRecordList) {
13 | List newLeadList = (List)this.recordList;
14 |
15 | for(Lead newLead : newLeadList) {
16 | this.setStatus(newLead);
17 | }
18 | }
19 |
20 | private void setStatus(Lead lead) {
21 | // Add logic here. Methods should be simple & independent from each other (except for overloaded methods)
22 | lead.Status = 'Open - Not Contacted';
23 | }
24 | }
25 |
26 | static List leadList = new List();
27 |
28 | static void setupData() {
29 | for(Integer i = 0; i < 5; i++) {
30 | Lead lead = new Lead(
31 | Company = 'My Test Company',
32 | LastName = 'Gillespie',
33 | Status = ''
34 | );
35 | leadList.add(lead);
36 | }
37 | insert leadList;
38 | }
39 |
40 | @isTest
41 | static void shouldNotExecuteTriggers() {
42 | NebulaTriggerHandlerSettings__c triggerHandlerSettings = NebulaTriggerHandlerSettings__c.getInstance();
43 | triggerHandlerSettings.ExecuteTriggers__c = false;
44 | upsert triggerHandlerSettings;
45 |
46 | LeadTriggerHandlerTest leadTriggerHandler = new LeadTriggerHandlerTest();
47 | leadTriggerHandler.currentTriggerContext = SObjectTriggerHandler.TriggerContext.BEFORE_INSERT;
48 | leadTriggerHandler.recordList = leadList;
49 |
50 | Test.startTest();
51 |
52 | leadTriggerHandler.execute();
53 |
54 | Test.stopTest();
55 | }
56 |
57 | // @isTest
58 | // static void executeAllContexts() {
59 | // setupData();
60 | // LeadTriggerHandlerTest leadTriggerHandler = new LeadTriggerHandlerTest();
61 | // leadTriggerHandler.recordList = leadList;
62 |
63 | // Test.startTest();
64 | // for(SObjectTriggerHandler.TriggerContext context : SObjectTriggerHandler.TriggerContext.values()) {
65 | // leadTriggerHandler.currentTriggerContext = context;
66 | // leadTriggerHandler.execute();
67 | // }
68 | // Test.stopTest();
69 | // }
70 |
71 | // @isTest
72 | // static void executeBeforeInsert() {
73 | // LeadTriggerHandlerTest leadTriggerHandler = new LeadTriggerHandlerTest();
74 | // // Set the variables for the relevant context
75 | // leadTriggerHandler.currentTriggerContext = SObjectTriggerHandler.TriggerContext.BEFORE_INSERT;
76 | // leadTriggerHandler.recordList = leadList;
77 |
78 | // Test.startTest();
79 |
80 | // leadTriggerHandler.execute();
81 |
82 | // Test.stopTest();
83 | // }
84 |
85 | // @isTest
86 | // static void executeBeforeUpdate() {
87 | // LeadTriggerHandlerTest leadTriggerHandler = new LeadTriggerHandlerTest();
88 | // // Set the variables for the relevant context
89 | // leadTriggerHandler.currentTriggerContext = SObjectTriggerHandler.TriggerContext.BEFORE_UPDATE;
90 | // leadTriggerHandler.recordList = leadList;
91 | // leadTriggerHandler.recordMap = new Map(leadList);
92 | // leadTriggerHandler.oldRecordList = leadList;
93 | // leadTriggerHandler.oldRecordMap = new Map(leadList);
94 |
95 | // Test.startTest();
96 |
97 | // leadTriggerHandler.execute();
98 |
99 | // Test.stopTest();
100 | // }
101 |
102 | }
--------------------------------------------------------------------------------
/nebula-app-framework/main/query-and-search/classes/QueryArgumentFormatter.cls:
--------------------------------------------------------------------------------
1 | /*************************************************************************************************
2 | * This file is part of the Nebula Framework project, released under the MIT License. *
3 | * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
4 | *************************************************************************************************/
5 |
6 | /**
7 | *
8 | * @group Query Builder
9 | *
10 | * @description TODO
11 | *
12 | */
13 | public virtual class QueryArgumentFormatter extends NebulaCore implements IQueryArgumentFormatter {
14 |
15 | private String value;
16 |
17 | public QueryArgumentFormatter(Object valueToFormat) {
18 | this.currentModule = NebulaCore.Module.QUERY_BUILDER;
19 | this.value = this.objectToQueryString(valueToFormat);
20 | }
21 |
22 | public virtual String getValue() {
23 | return this.value;
24 | }
25 |
26 | protected virtual String objectToQueryString(Object valueToFormat) {
27 | if(valueToFormat == null) return null;
28 | else if(CollectionUtils.isList(valueToFormat)) return this.listToQueryString((List