Data Access Flow

Last Updated: May 19, 2025

This document provides a concise overview of data access patterns in the Typus Development Framework.

Overview

The Typus Framework offers three complementary approaches to data access:

  1. DSL Models - The primary and recommended approach
  2. Prisma ORM - For direct database access
  3. Service-based SQL - For complex or specialized queries

Data Access Approaches

Application

DSL Models

Prisma ORM

Service Layer

Prisma Adapter

Database

Raw SQL

DSL Model Approach

The Domain-Specific Language (DSL) model approach provides a unified data access layer across the entire application.

Flow

DatabasePrisma ORMDSL HooksDSL ServiceAPI LayerFrontend/DispatcherDatabasePrisma ORMDSL HooksDSL ServiceAPI LayerFrontend/DispatcherDSL.User.findMany()Execute operationBefore hooksModified requestPrisma querySQL queryResult setTyped resultsAfter hooksModified resultsResponseTyped data

Key Features

  • Unified Syntax: Same API across frontend, backend, and dispatcher
  • Type Safety: Full TypeScript support throughout the stack
  • Hooks System: Centralized business logic with before/after hooks
  • Access Control: Built-in permission enforcement

Example

// Frontend
const users = await DSL.User.findMany({ 
  where: { role: 'admin' },
  include: { profile: true }
});

// Backend
const users = await this.dslService.executeOperation(
  'User',
  'findMany',
  { where: { role: 'admin' }, include: { profile: true } }
);

Prisma ORM Approach

Direct Prisma ORM access is available for more complex database operations.

Flow

DatabasePrisma ClientService LayerDatabasePrisma ClientService Layerprisma.user.findMany()SQL queryResult setTyped results

Key Features

  • Rich Query API: Complex filters, relations, and aggregations
  • Type Safety: Generated types based on schema
  • Transaction Support: Atomic operations
  • Performance: Optimized query generation

Example

// In a service
const users = await this.prisma.user.findMany({
  where: {
    role: 'admin',
    posts: { some: { published: true } }
  },
  include: {
    profile: true,
    posts: { where: { published: true } }
  }
});

Service-based SQL Approach

For specialized needs, direct SQL queries can be executed through service layers.

Flow

DatabaseService LayerControllerDatabaseService LayerControllergetUserAnalytics()Execute raw SQLResult setProcessed results

Key Features

  • Maximum Flexibility: Full SQL capabilities
  • Performance Optimization: Hand-crafted queries for specific needs
  • Complex Joins: Multi-table operations beyond ORM capabilities
  • Specialized Functions: Database-specific features

Example

// In a specialized service
const analytics = await this.dbService.executeRawQuery(`
  SELECT 
    u.id, 
    u.name, 
    COUNT(p.id) as post_count,
    AVG(p.view_count) as avg_views
  FROM users u
  LEFT JOIN posts p ON u.id = p.author_id
  WHERE u.created_at > $1
  GROUP BY u.id, u.name
  HAVING COUNT(p.id) > 5
  ORDER BY avg_views DESC
  LIMIT 10
`, [oneMonthAgo]);

Choosing the Right Approach

  • DSL Models: For most application data access needs (recommended)
  • Prisma ORM: For complex queries with relations and aggregations
  • Service-based SQL: For performance-critical or highly specialized queries

Best Practices

  1. Start with DSL: Begin with DSL models for all data access
  2. Escalate as Needed: Move to Prisma for complex queries
  3. SQL as Last Resort: Use raw SQL only when necessary
  4. Encapsulate Complexity: Keep raw SQL in dedicated services
  5. Maintain Type Safety: Create interfaces for raw SQL results

Conclusion

The Typus Framework provides a flexible, layered approach to data access. By starting with the high-level DSL abstraction and dropping down to lower levels only when necessary, developers can balance productivity, type safety, and performance.

WARNING

Failed to fetch dynamically imported module: https://typus.dev/assets/RecursiveNavItem-Cep7andh.js

{ "stack": "AppError: Failed to fetch dynamically imported module: https://typus.dev/assets/RecursiveNavItem-Cep7andh.js\n at https://typus.dev/assets/index-DS79FI73.js:315:420\n at dn (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:13:1385)\n at We (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:13:1455)\n at Ws.t.__weh.t.__weh (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:14:7364)\n at jt (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:13:1866)\n at v (https://typus.dev/assets/vue-vendor-Ct83yDeK.js:14:4019)\n at https://typus.dev/assets/vue-vendor-Ct83yDeK.js:14:4097" }