Overview
A full-featured query translation module typically exceeds 1000 lines of code. This approach suits full-featured databases and requires deep understanding of Forest’s internals.
Key steps
Implementing this strategy requires completing three main phases:- Structure declaration - Define the data structure
- Capabilities declaration - Specify API capabilities
- Translation layer implementation - Code the actual query translation
Minimal example
Structure declaration
Columns
Define fields with types, validation, and default values:Typing
The typing system for columns is the same as the one used when declaring fields in the back-end customization step.Validation
Forest permits declaring validation rules on primitive-type fields. These rules validate records during creation/updating in the back-office interface. The validation API mirrors the condition tree structure but excludes a “field” entry. Example validation clause:Relationships
Important: Only intra-datasource relationships belong at the collection level. For inter-datasource relationships, use jointures during customization. Data sources using the query translation strategy require careful implementation for relationships.Capabilities declaration
Data source implementers don’t need to translate every possible query type. Forest ensures only supported query features are available by having collections declare capabilities on construction.Required features
All datasources must support:- Listing records
Andnodes in condition treesOrnodes in condition treesEqualoperator on primary keys- Paging (
skip,limit)
Or node is a strong constraint, as many backends will not allow it: providing a working implementation may require making multiple queries and recombining the results.
Optional features (opt-in)
UI filter requirements by field type
To unlock GUI filtering:- Boolean:
Equal,NotEqual,Present,Blank - Date: All date operators
- Enum:
Equal,NotEqual,Present,Blank,In - Number:
Equal,NotEqual,Present,Blank,In,GreaterThan,LessThan - String:
Equal,NotEqual,Present,Blank,In,StartsWith,EndsWith,Contains,NotContains - UUID:
Equal,NotEqual,Present,Blank
Collection-level capabilities
Count
Enables pagination widget to display total page count. Requires implementing theaggregate method:
Search
Allows custom search implementation instead of default condition tree approach. Useful for full-text search (ElasticSearch, etc.):Segments
Define segments at datasource level when condition trees are insufficient or segments are shared across projects:Field-level capabilities
Write support
Mark fields as read-only:Filtering operators
Declare supported operators per field:Sort support
Flag sortable fields:Read implementation
Emulation strategy
Emulation enables rapid development by allowing features to be tested in Node.js before optimization. This approach trades performance for faster iteration.Basic list implementation
Aggregate method
Theaggregate method handles both record counting and chart data generation:
Optimization: count queries
Handle count operations separately if your API supports efficient counting:Write implementation
Making your records editable is achieved by implementing thecreate, update and delete methods.
Important: The three write methods accept filter parameters, but unlike the list method, pagination support is unnecessary.
Method details
- create(): Must return the newly created records with all fields populated
- update(): Receives filter and patch object; updates matching records
- delete(): Receives filter; deletes all matching records
Intra-datasource relationships
When building your own datasources using the translation strategy, collections must handle intra-datasource relationships that are declared in their structure.Relationship types and requirements
Automatic handling:one-to-manyrelationshipsmany-to-manyrelationships
many-to-onerelationshipsone-to-onerelationships
Handling prefixed fields
When amany-to-one relationship exists, the collection must accept references using dot notation throughout its operations.
Structure declaration example
Query example
The system can execute calls using both source and target collection fields:Expected response structure
Implementation scope
Developers implementing your own datasources must handle prefixed field references in:- Filters (condition trees)
- Projections (field selections)
- Aggregations (calculation operations)
Want to share your datasource with the community? Check out the Forest experimental repository to contribute.