Releases: beyond-the-cloud-dev/soql-lib
v6.10.0
v6.10.0 - 12-May-2026
Scope
- New Feature:
@NamespaceAccessibleSupport for Managed Packages - Enhancement:
CacheManagerFallback to Apex Transaction Cache - Fix:
Cache.SessionAvailability Handling - Fix: Mocking with Schema-Prefixed SObject Types
- Fix: Encrypted Field Usage in Tests
- Maintenance: PMD Suppressions, Prettier Formatting, Dependency Bumps
SOQL, SOQLCache, SOQLEvaluator, and CacheManager
- Added
@NamespaceAccessibleannotation to public access points acrossSOQL,SOQLCache, andSOQLEvaluator CacheManagernow falls back to in-memory Apex transaction cache when the platform cache partition is unavailable- Hardened
Cache.SessionandCache.Orgpartition retrieval against exceptions and unavailable session contexts
New Feature: @NamespaceAccessible Support for Managed Packages
All public access points of SOQL, SOQLCache, and SOQLEvaluator are now annotated with @NamespaceAccessible. This allows the library to be consumed from other Apex code in subscriber orgs when distributed as a managed package, without requiring global visibility.
Affected public surface (examples)
@NamespaceAccessible
public virtual inherited sharing class SOQLCache implements Cacheable {
@NamespaceAccessible
public interface Selector {
Cacheable query();
}
@NamespaceAccessible
public static Cacheable of(SObjectType ofObject) {
return new SOQLCache(ofObject);
}
// ...
}The annotation has been applied to:
- Static factory methods (
SOQL.of(...),SOQLCache.of(...),SOQLEvaluator.of(...)) - Public interfaces (
Selector,Queryable,Cacheable,Mockable, etc.) - Public constructors and entry-point methods (
mock,removeFromCache, fluent builders)
No behavioral change for unmanaged usage — the annotation only affects access from outside the package namespace.
Enhancement: CacheManager Fallback to Apex Transaction Cache
CacheManager (v1.1.0) now gracefully degrades when a platform cache partition is unavailable (e.g. partition not provisioned, no cache capacity allocated, or session cache not available in the current context). Instead of throwing an exception, reads and writes are transparently routed to an in-memory ApexTransactionCache fallback for the lifetime of the transaction.
What changed
- Added a private
fallbackfield of typeApexTransactionCacheto the abstractPlatformCacheclass - All
Cacheableoperations (contains,getKeys,get,put,remove) checkisAvailable()and route to either the platform partition or the fallback OrgPlatformCache.getPartition(...)now catchesCache.Org.OrgCacheExceptionand returnsnullSessionPlatformCache.getPartition(...)now checksCache.Session.isAvailable()and catchesCache.Session.SessionCacheException, returningnullon either condition
Behavior
// When the SOQL cache partition is missing or session cache is unavailable,
// SOQLCache continues to function — caching happens in-memory for the current transaction.
SOQLCache.of(Account.SObjectType)
.cacheInSessionCache()
.whereEqual(Account.Name, 'Test')
.toObject();Fix: Cache.Session Availability Handling
Refactored SessionPlatformCache.getPartition(...) so that the Cache.Session.isAvailable() check is performed inside the try block. This ensures consistent null handling when the session cache is genuinely unavailable (e.g. in contexts where no default cache partition is configured).
Before
public override Cache.Partition getPartition(String partitionName) {
if (!Cache.Session.isAvailable()) {
return null;
}
try {
return Cache.Session.getPartition(partitionName);
} catch (Cache.Session.SessionCacheException e) {
return null;
}
}After
public override Cache.Partition getPartition(String partitionName) {
try {
if (!Cache.Session.isAvailable()) {
return null;
}
return Cache.Session.getPartition(partitionName);
} catch (Cache.Session.SessionCacheException e) {
return null;
}
}Fix: Mocking with Schema-Prefixed SObject Types
Fixed an issue in SOQL.stripAdditionalFields(...) where constructing the cleaned record list via Type.forName('List<' + objectTypeName + '>') could fail to resolve the SObject type in certain namespaces or when the type token did not round-trip through Type.forName. The list type is now built using the explicit Schema. prefix for known SObject types.
Before
List<SObject> cleanedRecords = (List<SObject>) Type.forName('List<' + objectTypeName + ' >').newInstance();After
List<SObject> cleanedRecords = (List<SObject>) Type.forName(
'List<' + (this.sObjectType != null ? 'Schema.' + this.sObjectType.toString() : 'SObject') + ' >'
).newInstance();Fix: Encrypted Field Usage in Tests
Updated tests that previously filtered or projected on Account.Name and Account.Industry in scenarios where the record was expected not to exist. These tests now use Account.DunsNumber and Account.Industry instead, avoiding flakiness in orgs that have classic encryption (or platform encryption) enabled on the Name field.
Affected tests in SOQL_Test / SOQL_Full_Test:
toValueOfWhenRecordNotExisttoValuesOfRelationshipFieldWhenRelatedRecordNotExistpreviewWithConditions
Maintenance
PMD Suppressions
- Added
PMD.NcssCountto the suppressed warnings on theSOQLclass to align with existingPMD.NcssTypeCountsuppression (the library intentionally lives in a single class for fluent usage).
Prettier Formatting
- Repository-wide reformatting with Prettier (incl.
prettier-plugin-apexand@prettier/plugin-xml). - Added a root
package.jsondeclaring the Prettier toolchain as dev dependencies:
{
"name": "soql-lib",
"private": true,
"version": "1.0.0",
"devDependencies": {
"@prettier/plugin-xml": "^3.4.1",
"prettier": "^3.4.2",
"prettier-plugin-apex": "^2.2.1"
}
}v6.9.0
v6.9.0 - 27-March-2026
Scope
- New Feature:
toLabel()Support for SubQuery - New Feature:
toLabel()with List of Fields - Project Structure Reorganization
- AI Coding Rules & Skills
SOQL, SOQLCache, and SOQLEvaluator
- Added
toLabel()methods toSubQueryinterface (5 overloads) - Added
toLabel(Iterable<String> fields)method toQueryableinterface
New Feature: toLabel() Support for SubQuery
SubQuery now supports the toLabel() function, allowing you to retrieve translated picklist values in sub-queries. Five overloads are available, matching the parent query API.
Example: SubQuery toLabel with SObjectField
String soql = SOQL.of(Account.SObjectType)
.with(SOQL.SubQuery.of('Contacts')
.with(Contact.LastName)
.toLabel(Contact.Salutation)
).toString();
// SELECT Id , (SELECT LastName, toLabel(Salutation) FROM Contacts) FROM AccountExample: SubQuery toLabel with Alias
String soql = SOQL.of(Account.SObjectType)
.with(SOQL.SubQuery.of('Contacts')
.with(Contact.LastName)
.toLabel(Contact.Salutation, 'contactSalutation')
).toString();
// SELECT Id , (SELECT LastName, toLabel(Salutation) contactSalutation FROM Contacts) FROM AccountExample: SubQuery toLabel with String Field (for relationship fields)
String soql = SOQL.of(Account.SObjectType)
.with(SOQL.SubQuery.of('Contacts')
.with(Contact.LastName)
.toLabel('MyCustomObject__r.Name')
).toString();
// SELECT Id , (SELECT LastName, toLabel(MyCustomObject__r.Name) FROM Contacts) FROM AccountExample: SubQuery toLabel with List of String Fields
String soql = SOQL.of(Account.SObjectType)
.with(SOQL.SubQuery.of('Contacts')
.toLabel(new List<String>{ 'Salutation', 'MyCustomObject__r.Name' })
).toString();
// SELECT Id , (SELECT toLabel(Salutation), toLabel(MyCustomObject__r.Name) FROM Contacts) FROM AccountNew Feature: toLabel() with List of Fields
Added a new toLabel(Iterable<String> fields) method that allows applying toLabel() to multiple fields at once, reducing boilerplate when translating several picklist fields.
Before (v6.8.0)
SOQL.of(Lead.SObjectType)
.with(Lead.Company, Lead.Status)
.toLabel('Status')
.toLabel('MyCustomObject__r.Name')
.toString();After (v6.9.0)
SOQL.of(Lead.SObjectType)
.with(Lead.Company, Lead.Status)
.toLabel(new List<String>{ 'Status', 'MyCustomObject__r.Name' })
.toString();
// SELECT Company, Status, toLabel(Status), toLabel(MyCustomObject__r.Name) FROM LeadProject Structure Reorganization
Restructured the project directories for better separation between the distributable package and development/test resources.
Before (v6.8.0)
force-app/ → Main package source (SOQL, SOQLCache, SOQLEvaluator, CacheManager)
internal/ → Full test classes (SOQL_Full_Test, SOQLCache_Full_Test, SOQLEvaluator_Full_Test)
examples/ → Example selectors and usage
After (v6.9.0)
package/ → Distributable package source (SOQL, SOQLCache, SOQLEvaluator, CacheManager + Full Test classes)
force-app/ → Development source (main classes + reduced test classes)
examples/ → Example selectors and usage (+ new cached selectors)
Key changes:
- The managed/unlocked package path moved from
force-app/topackage/ - Full test classes (
SOQL_Full_Test,SOQLCache_Full_Test,SOQLEvaluator_Full_Test) moved into thepackage/directory alongside the source - The
internal/directory was removed - Cache Partition metadata (
SOQL.cachePartition-meta.xml) added to the package forSOQLCacheOrg/Session cache support
AI Coding Rules & Skills
Added AI-assisted development rules and skills for Claude Code, Cursor, and A4D (Agentforce for Developers):
- Claude Code rules (
.claude/rules/):soql-lib-queries.md,soql-lib-selectors.md,soql-lib-testing.md - Cursor skills (
.cursor/skills/):soql-lib-query-builder,soql-lib-selector,soql-lib-testing - Agentforce rules (
.a4drules/):01-soql-lib-queries.md,02-soql-lib-selectors.md,03-soql-lib-testing.md
These rules help AI coding assistants generate correct SOQL Lib code by providing patterns, conventions, and best practices specific to this library.
v6.8.0
v6.8.0 - 02-March-2026
Scope
- New Feature: Pagination Cursor Support
- Performance Improvements
- Test Suite Reorganization
- API Version Update
SOQL and SOQLCache
- Added
toPaginationCursor()method for pagination support - Optimized
toIdsOf()andtoValuesOf()query performance - Enhanced
SOQLCache.toId()andSOQLCache.toIdOf()methods - Updated to Salesforce API 66.0
New Feature: Pagination Cursor Support
SOQL Lib now supports Database Pagination Cursors, enabling efficient pagination through large result sets. This is particularly useful for building paginated user interfaces and REST APIs.
Example: Basic Pagination Cursor Usage
Database.PaginationCursor cursor = SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.orderBy(Account.Name)
.toPaginationCursor();
// Use the cursor for pagination
// cursor.getPageSize(), cursor.hasNext(), etc.Example: Pagination Cursor with Sharing Mode
// Respect sharing rules
Database.PaginationCursor cursor = SOQL.of(Opportunity.SObjectType)
.systemMode()
.withSharing()
.toPaginationCursor();
// Bypass sharing rules
Database.PaginationCursor cursor = SOQL.of(Opportunity.SObjectType)
.systemMode()
.withoutSharing()
.toPaginationCursor();Performance Improvements
Optimized toIdsOf() and toValuesOf() Query Performance
Enhanced toIdsOf() and toValuesOf() methods to use COUNT(Id) aggregate function, significantly reducing the number of query rows consumed. This optimization helps stay within Salesforce governor limits when extracting unique values from large datasets.
Before (v6.7.0)
-- Generated query consumed all matching rows
SELECT ParentId, Id
FROM Account
WHERE ParentId != null
GROUP BY ParentIdAfter (v6.8.0)
-- Generated query consumes only unique groups
SELECT ParentId, Id, COUNT(Id)
FROM Account
WHERE ParentId != null
GROUP BY ParentIdBenefits:
- Significantly reduces query row consumption
- Helps avoid "Too many query rows" governor limit errors
- Particularly beneficial when working with large datasets containing many duplicate values
- No changes required to your code - the optimization is automatic
Example:
// Automatically optimized to use COUNT(Id)
Set<Id> parentIds = SOQL.of(Account.SObjectType)
.toIdsOf(Account.ParentId);
Set<String> accountNames = SOQL.of(Account.SObjectType)
.toValuesOf(Account.Name);SOQLCache Enhancements
Improved toId() and toIdOf() Methods
Enhanced SOQLCache.toId() and SOQLCache.toIdOf() methods to automatically include the required fields in the query, eliminating the need for manual field selection.
Before (v6.7.0)
// Had to manually specify Id field
Id accountId = SOQL_Account.query()
.with(Account.Id)
.byId(someId)
.toId();After (v6.8.0)
// Id field is automatically included
Id accountId = SOQL_Account.query()
.byId(someId)
.toId();
// Also works for related fields
Id parentId = SOQL_Account.query()
.byId(someId)
.toIdOf(Account.ParentId);Test Suite Reorganization
Refactored the test suite for better maintainability and faster deployment:
- Created
internal/folder - Houses comprehensive test classes that don't deploy to production - Split test classes:
SOQL_Full_Test.cls(5,260+ lines) - Comprehensive SOQL testsSOQLCache_Full_Test.cls(1,244+ lines) - Comprehensive cache testsSOQLEvaluator_Full_Test.cls(674+ lines) - Comprehensive evaluator tests
- Reduced main test classes - Core
SOQL_Test.clsreduced from ~5,000 to ~1,000 lines for faster deployment - Added
.prettierrc- Configured code formatting standards
This reorganization significantly improves deployment speed while maintaining comprehensive test coverage for development.
API Version Update
Updated all meta files to support Salesforce API version 66.0, ensuring compatibility with the latest Salesforce features and improvements.
🚨 Breaking Changes 🚨
There are no breaking changes in this release. All improvements are internal optimizations or additive features that maintain full backward compatibility:
- Existing queries continue to work exactly as before
- Performance optimizations are automatic and transparent
- New
toPaginationCursor()method is an addition to the existing API
v6.7.0
v6.7.0 - 20-January-2026
Scope
- New Feature: Database Cursor Support
- Mocking Improvements
- Filter Enhancements
SOQL
- Added
toCursor()method for Database Cursor support - Simplified mocking with automatic SObjectType-based mocking
- Enhanced
isIn()andnotIn()filters to accept SObject collections - Improved mocking documentation and examples
New Feature: Database Cursor Support
SOQL Lib now supports Database Cursors, enabling efficient processing of large datasets with reduced memory footprint. Cursors are ideal for batch operations and handling millions of records.
Example: Basic Cursor Usage
Database.Cursor queryCursor = SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toCursor();
System.debug('Total Records: ' + queryCursor.getNumRecords());Example: Cursor with Sharing Mode
// Respect sharing rules
Database.Cursor queryCursor = SOQL.of(Task.SObjectType)
.systemMode()
.withSharing()
.toCursor();
// Bypass sharing rules
Database.Cursor queryCursor = SOQL.of(Task.SObjectType)
.systemMode()
.withoutSharing()
.toCursor();Mocking Improvements
Automatic SObjectType-Based Mocking
Previously, every query required a unique mockId() to be set. Now, SOQL Lib automatically uses the SObjectType for mocking, eliminating the need for explicit mock IDs in most cases.
Before (v6.6.0)
// Controller
public static List<Account> getAllAccounts() {
return SOQL.of(Account.SObjectType)
.with(Account.Name)
.mockId('ExampleController.getAllAccounts') // Required
.toList();
}
// Test
SOQL.mock('ExampleController.getAllAccounts').thenReturn(mockAccounts);After (v6.7.0)
// Controller - No mockId() needed!
public static List<Account> getAllAccounts() {
return SOQL.of(Account.SObjectType)
.with(Account.Name)
.toList();
}
// Test - Mock by SObjectType
SOQL.mock(Account.SObjectType).thenReturn(mockAccounts);How It Works:
- Every query automatically gets a default mock ID based on its SObjectType hash
- You can still use explicit
mockId()when you need different mocks for the same SObjectType - Explicit
mockId()always takes precedence over SObjectType-based mocking
Example: Using Both Approaches
SOQL.mock('specificQuery').thenReturn(specificMock);
SOQL.mock(Account.SObjectType).thenReturn(defaultMock);
// This uses the specific mock
queryable.mockId('specificQuery').toList();
// This uses the SObjectType mock
SOQL.of(Account.SObjectType).toList();Filter Enhancements
Skip Collection Looping with isIn() and notIn()
New overloaded methods for isIn() and notIn() that accept SObject collections, eliminating the need for manual collection iteration and value extraction.
Before (v6.6.0)
Set<String> accountNames = new Set<String>();
for (Account acc : accounts) {
accountNames.add(acc.Name);
}
List<Contact> contacts = SOQL.of(Contact.SObjectType)
.whereAre(SOQL.Filter.with(Contact.AccountName__c).isIn(accountNames))
.toList();After (v6.7.0)
List<Contact> contacts = SOQL.of(Contact.SObjectType)
.whereAre(SOQL.Filter.with(Contact.AccountName__c).isIn(accounts, Account.Name))
.toList();Key Features:
- Automatically extracts values from the specified field
- Skips null values to prevent query errors
- Works with any SObjectField
- Supports both
isIn()andnotIn()filters
Example: Filtering with Null Handling
// Even if some accounts have null Names, the query works correctly
List<Account> accounts = new List<Account>{
new Account(Name = 'Account 1'),
new Account(Name = 'Account 2'),
new Account(Name = null) // Automatically skipped
};
List<Contact> contacts = SOQL.of(Contact.SObjectType)
.whereAre(SOQL.Filter.with(Contact.AccountName__c).isIn(accounts, Account.Name))
.toList();v6.6.0
v6.6.0 - 21-December-2025
Scope
- Bug Fixes
- Mocking Improvements
SOQL
- Fixed Base64/Blob field deserialization issue in mocking
- Fixed empty list mocking for
toIdsOf()andtoValuesOf()
Bug Fixes
Base64/Blob Field Deserialization Fix
Fixed an issue where mocking objects with Base64 or Blob fields (such as StaticResource.Body) would cause JSON deserialization errors. The library now gracefully falls back to returning the original record when JSON deserialization fails.
Example: Mocking StaticResource with Blob
@IsTest
static void mockingSingleRecordWithBlob() {
StaticResource testResource = new StaticResource(
Name = 'Test 1',
Body = Blob.valueOf('Test 1 Body')
);
SOQL.mock('mockingQuery').thenReturn(testResource);
StaticResource result = (StaticResource) SOQL.of(StaticResource.SObjectType)
.with(StaticResource.Name, StaticResource.Body)
.mockId('mockingQuery')
.toObject();
Assert.areEqual(testResource, result);
}Empty List Mocking Fix
Fixed an issue where mocking toIdsOf() and toValuesOf() with an empty list would throw an error instead of returning an empty set.
Example: Mocking Empty Results
@IsTest
static void toIdsOfWithMockingEmptyList() {
SOQL.mock('mockingQuery').thenReturn(new List<Account>());
Set<Id> parentIds = SOQL.of(Account.SObjectType)
.mockId('mockingQuery')
.toIdsOf(Account.ParentId);
Assert.areEqual(0, parentIds.size());
}🚨 Breaking Changes 🚨
There are no breaking changes in this release. All changes are bug fixes and internal improvements that maintain backward compatibility.
v6.5.0
v6.5.0 - 15-November-2025
Scope
- Mocking Improvements
- API Version Update
- Bug Fixes
SOQL
- Simplified mocking for
toIdsOf()andtoValuesOf()methods - Updated to Salesforce API 65.0
Mocking Improvements
Simplified toIdsOf() and toValuesOf() Mocking
Previously, mocking toIdsOf() and toValuesOf() required complex AggregateResult JSON deserialization. Now, you can simply pass a list of SObjects.
Before (v6.4.0)
SOQL.mock('mockingQuery').thenReturn(
(List<AggregateResult>) JSON.deserialize(
JSON.serialize(new List<Map<String, Object>>{
new Map<String, Object>{ 'Id' => 'Account Name 1' },
new Map<String, Object>{ 'Id' => 'Account Name 2' }
}),
List<AggregateResult>.class
)
);After (v6.5.0)
SOQL.mock('mockingQuery').thenReturn(new List<Account>{
new Account(Name = 'Test 1'),
new Account(Name = 'Test 2')
});API Version Update
Updated all meta files to support Salesforce API version 65.0, ensuring compatibility with the latest Salesforce features and improvements.
v6.4.0
v6.3.0
v6.2.0
v6.2.0 - 18-October-2024
Scope
- Enhanced Mocking Capabilities
- Documentation Update
SOQL
- Added support for mocking query exceptions
- Improved error testing capabilities
Mocking Query Exceptions
SOQL Lib now supports mocking query exceptions, enabling you to test error handling scenarios in your Apex code. This is essential for validating that your application gracefully handles database errors, security violations, and other query-related exceptions.
Default Exception Mock
Use .throwException() to simulate a standard query exception with the default message: "List has no rows for assignment to SObject".
Controller
public with sharing class ExampleController {
public static Account getAccountById(Id accountId) {
try {
return (Account) SOQL.of(Account.SObjectType)
.with(Account.Name, Account.BillingCity)
.byId(accountId)
.mockId('ExampleController.getAccountById')
.toObject();
} catch (Exception e) {
// Logger here
throw e;
}
}
}Test Class
@IsTest
static void getAccountByIdException() {
SOQL.mock('ExampleController.getAccountById').throwException();
Test.startTest();
Exception error;
try {
Account result = ExampleController.getAccountById('001000000000000AAA');
} catch (Exception e) {
error = e;
}
Test.stopTest();
Assert.isNotNull(error, 'The query exception should be thrown.');
}Custom Exception Message Mock
Use .throwException(message) to simulate a query exception with a custom error message, such as field-level security errors or invalid field references.
Test Class
@IsTest
static void getAccountByIdException() {
String errorMessage = 'No such column \'InvalidField__c\' on entity \'Account\'.';
SOQL.mock('ExampleController.getAccountById').throwException(errorMessage);
Test.startTest();
Exception error;
try {
Account result = ExampleController.getAccountById('001000000000000AAA');
} catch (Exception e) {
error = e;
}
Test.stopTest();
Assert.isNotNull(error, 'The query exception should be thrown.');
Assert.isTrue(error.getMessage().contains('InvalidField__c'));
}Documentation Update
Added comprehensive documentation for exception mocking, including:
- Detailed examples of both default and custom exception messages
- Best practices for testing error handling scenarios
- Integration examples with controller error handling patterns
🚨 Breaking Changes 🚨
There are no breaking changes in this release. All new features are additive.
v6.1.0
v6.1.0 - September 14, 2025
Scope
- NEW: Enhanced Result Mapping with ID-based Methods
- IMPROVED: Automatic Performance Optimization with Null Checking
- IMPROVED: Documentation Website UI/UX Enhancements
- IMPROVED: Code Formatting Optimization - Converted Indentation to Tabs
Major New Features
Enhanced Result Mapping - ID-based Methods
The biggest addition to v6.1.0 is the introduction of new ID-focused result mapping methods that provide more precise control over how query results are transformed into maps using ID keys.
New ID Mapping Methods
// Map records by any ID field
Map<Id, Account> ownerIdToAccount = (Map<Id, Account>) SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toIdMapBy(Account.OwnerId);
// Map records by relationship ID fields
Map<Id, Account> parentIdToAccount = (Map<Id, Account>) SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toIdMapBy('Parent', Account.Id);
// Group multiple records by ID field
Map<Id, List<Account>> ownerIdToAccounts = (Map<Id, List<Account>>) SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toAggregatedIdMapBy(Account.OwnerId);
// Group multiple records by relationship ID field
Map<Id, List<Account>> parentIdToAccounts = (Map<Id, List<Account>>) SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toAggregatedIdMapBy('Parent', Account.Id);Automatic Performance Optimization
Smart Null Checking for Better Query Performance
All mapping methods (toMap, toAggregatedMap, toIdMapBy, toAggregatedIdMapBy) now automatically add null-checking conditions to improve query performance:
WHERE keyField != null- Automatically added for direct field mappingWHERE relationshipName.targetKeyField != null- Automatically added for relationship field mapping
This optimization reduces result set size and improves query execution time by filtering out records with null key values that would be unusable in the resulting maps.
Traditional Approach:
// Manual null checking required
Map<Id, Account> ownerIdToAccount = new Map<Id, Account>();
for (Account acc : [SELECT Id, Name, OwnerId FROM Account WHERE OwnerId != null]) {
ownerIdToAccount.put(acc.OwnerId, acc);
}SOQL Lib Approach:
// Automatic null checking built-in
Map<Id, Account> ownerIdToAccount = (Map<Id, Account>) SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toIdMapBy(Account.OwnerId);Documentation and UI Improvements
Enhanced Documentation Website
Light/Dark Mode Compatibility
- Fixed homepage text visibility issues in light mode
- Improved contrast and readability across all themes
- Enhanced user experience with responsive color schemes
Comprehensive Method Documentation
- Added complete documentation for all new ID mapping methods
- Included practical examples showing traditional vs SOQL Lib approaches
- Added performance optimization notes for all mapping methods
- Enhanced code examples with field selection for better clarity
Code Formatting Optimization
Indentation Converted to Tabs
- Converted all code indentation from spaces to tabs across the entire codebase
- Reduced character count by approximately 10% improving file size and load times
New Methods Reference
SOQL Result Methods
toIdMapBy(SObjectField field)
Creates a map where the key is the Id extracted from the specified field and the value is the SObject record.
toIdMapBy(String relationshipName, SObjectField targetKeyField)
Creates a map where the key is the Id extracted from the specified relationship field and the value is the SObject record.
toAggregatedIdMapBy(SObjectField keyField)
Creates a map where the key is the Id extracted from the specified field and the value is a list of SObject records grouped by that Id.
toAggregatedIdMapBy(String relationshipName, SObjectField targetKeyField)
Creates a map where the key is the Id extracted from the specified relationship field and the value is a list of SObject records grouped by that Id.
Contributors
Thank you @kaboomkazoom for your ideas and support!
Download: v6.1.0 Release
Documentation: https://soql.beyondthecloud.dev