Overview
The application layer orchestrates domain entities and infrastructure repositories through workflows that handle validation, business logic coordination, and error boundaries.
Application Layer
The application layer sits between your domain entities and infrastructure repositories, orchestrating business operations through workflows. Unlike use cases, workflows emphasize the flow of data and operations through validated pipelines using Effect's functional composition.
Complete Host Workflow Example
The following comprehensive example demonstrates all application layer patterns in action - from DTO creation through full workflow implementation:
We'll use schema-based DTOs instead of traditional class-based DTOs for better type safety and validation.
Build the creation DTO with required userId and optional profile fields. Notice we're composing with existing HostSchema.fields rather than redefining validation rules.
Create a partial update schema that picks specific fields and requires an ID. See Schema pick and extend function in Effect Schema API.
Add focused update schemas for address and social links.
Add minimal DTOs for basic operations.
Complete the DTO collection with a flexible query schema.
Start with the essential workflow setup and dependency injection.
Add the data initialization helper that handles defaults and timestamps.
Build the create operation with DTO validation and entity creation.
Add the profile update workflow that fetches existing data and merges changes.
Add focused update workflows for specific value objects.
Add straightforward CRUD operations with clean pipelines.
Add fetch operations that handle Option mapping and complex queries.
Complete the workflow with utility methods for profile management.
Key Lessons
-
Schema-First Validation: DTOs derive from domain entity schemas using
pick,partial, andextendto ensure consistency and reduce duplication while maintaining type safety. -
Effect Pipeline Composition: All workflows follow the pattern: validate input → transform data → call domain/repository → handle errors, using
pipefor predictable data flow. -
Dependency Injection: Workflows receive repository dependencies through constructor injection with
@injectable()and@inject()for clean separation and testability. -
Error Boundary Management: Clear separation between parse errors (schema validation), domain errors (business rules), and repository errors (persistence), with explicit
Optionto error mapping. -
Time and Identity Handling: Application layer manages
createdAt/updatedAttimestamps and UUID validation at workflow boundaries, keeping domain entities pure. -
Fetch-Merge Pattern: Update operations fetch existing entities, serialize to get current state, merge changes, and recreate entities to ensure all domain validations run.
-
Default Value Initialization: Private helpers provide sensible defaults for complex value objects (Address, SocialLinks) when not provided in requests.
-
Repository Method Coordination: Workflows orchestrate multiple repository calls (
fetchById,update,fetchByQuery) while maintaining transactional consistency through Effect composition.