Data Layer
Last Updated: May 19, 2025
This document provides an overview of the Data Layer in the Typus Development Framework, focusing on the Domain-Specific Language (DSL) system that enables consistent data access across frontend and backend.
Overview
The Typus Development Framework implements a unified data access layer through a Domain-Specific Language (DSL) system. This approach allows developers to use the same syntax and patterns for data operations regardless of where the code is executed - backend, frontend, or dispatcher.
The key feature of this system is the ability to write queries like user.findMany()
with identical syntax across the entire application stack, significantly reducing context switching and improving developer productivity.
Architecture
The DSL system consists of several interconnected components:
Key Components
Shared Registry
The shared registry is the central component that maintains model definitions accessible to all parts of the application:
- Model Definitions: Describes data structures, fields, and relationships
- Type Information: Provides TypeScript interfaces for type safety
- UI Metadata: Contains display information for frontend rendering
Backend DSL Service
The backend DSL service processes data operations:
- Operation Handling: Processes create, read, update, and delete operations
- Access Control: Enforces permissions based on user roles
- Hooks System: Provides before/after hooks for data manipulation
- Prisma Integration: Uses Prisma as the ORM layer to interact with the database
Frontend DSL Client
The frontend DSL client provides a type-safe API for data access:
- Type-Safe API: Offers strongly-typed methods for data operations
- Proxy-Based Access: Dynamically creates model clients on demand
- Consistent Interface: Mirrors the backend API for seamless integration
Dispatcher DSL Client
The task dispatcher uses the same DSL system for scheduled and background tasks:
- Consistent Data Access: Uses the same patterns as frontend and backend
- Background Processing: Handles data operations in scheduled tasks
- Event-Driven Operations: Responds to system events with data operations
Data Flow
A typical data operation flows through the system as follows:
- Client Request: Frontend or dispatcher makes a DSL request (e.g.,
user.findMany()
) - API Layer: Request is sent to the backend API
- DSL Controller: Backend DSL controller receives and validates the request
- DSL Service: Service processes the operation with appropriate hooks
- Prisma Layer: Prisma ORM translates the operation to database queries
- Database: Database executes the query and returns results
- Response Processing: Results flow back through the layers with appropriate transformations
Hooks System
The DSL system includes a powerful hooks mechanism that allows for custom logic at various points in the data lifecycle:
- Before Hooks: Execute before data operations (validation, transformation)
- After Hooks: Execute after data operations (enrichment, notifications)
- Custom Logic: Implement business rules without modifying core data access code
Example of registering a hook:
dslService.registerHook(
'User',
'beforeCreate',
(data) => {
// Custom logic before user creation
return data;
}
);
Prisma Integration
Currently, Prisma ORM serves as the data access layer between the DSL system and the database:
- Schema Definition: Prisma schema defines the database structure
- Query Building: Prisma translates DSL operations into optimized SQL
- Type Safety: Prisma provides TypeScript types that integrate with the DSL system
Usage Examples
Backend Usage
// In a backend service
const users = await this.dslService.executeOperation(
'User',
'read',
null,
{ role: 'admin' }
);
Frontend Usage
// In a Vue component
const users = await DSL.User.findMany({ role: 'admin' });
Dispatcher Usage
// In a scheduled task
const inactiveUsers = await DSL.User.findMany({
lastLoginAt: { lt: oneMonthAgo }
});
Benefits
The unified DSL approach provides several key benefits:
- Consistent Developer Experience: Same syntax across all application layers
- Reduced Context Switching: No need to learn different data access patterns
- Type Safety: Full TypeScript support throughout the stack
- Centralized Business Logic: Hooks provide a single place for business rules
- Simplified Testing: Consistent mocking approach for all data operations
Conclusion
The DSL system in the Typus Development Framework provides a powerful abstraction over data access, enabling developers to work with a consistent API regardless of where the code is executed. By centralizing model definitions and providing a unified interface, the system significantly improves developer productivity and code maintainability.
The current implementation uses Prisma as the ORM layer, but the architecture is designed to be adaptable to other data access technologies in the future.