Skip to content

Backend Layer

Overview

The PMN (Project Management Node) backend service is built using modern web technologies to provide a robust, scalable API for project management. The service follows a layered architecture pattern with clear separation of concerns and comprehensive error handling.

Technology Stack

Core Framework

  • Hono: Lightweight, fast web framework for Node.js
  • TypeScript: Full type safety and modern JavaScript features
  • Node.js: Runtime environment (18+)

Database & ORM

  • PostgreSQL: Primary relational database
  • Prisma: Type-safe database client and ORM
  • Redis: Caching and session storage

Authentication & Security

  • Casdoor: Identity and access management
  • JWT: JSON Web Token authentication
  • Zod: Schema validation and type safety

Search & Analytics

  • Elasticsearch: Full-text search capabilities
  • Typesense: Vector search and recommendations

Additional Services

  • BullMQ: Job queue management
  • Novu: Notification service
  • Sentry: Error tracking and monitoring
  • AWS S3: File storage service

Architecture Layers

1. Presentation Layer (Routes)

Purpose: Handle HTTP requests and responses

Structure:

src/routes/
├── access.ts          # Access control endpoints
├── addon.ts           # Addon management
├── attachment.ts      # File uploads
├── casdoor.ts         # Authentication
├── comment.ts         # Comment system
├── config.ts          # Configuration management
├── eNode.ts           # Project structure
├── excel.ts           # Import/export
├── follower.ts        # User following
├── history.ts         # Change tracking
├── invite.ts          # User invitations
├── issue.ts           # Work item management
├── link.ts            # Dependencies
├── marker.ts          # Visual indicators
├── migrate_to.ts      # Data migration
├── people.ts          # User management
├── reminder.ts        # Notifications
├── report.ts          # Analytics
├── template.ts        # Workflow templates
├── typesense.ts       # Search integration
└── view.ts            # Custom views

Key Features:

  • RESTful API design
  • OpenAPI documentation
  • Rate limiting
  • CORS support
  • Request validation

2. Business Logic Layer (Services)

Purpose: Implement core business logic and workflows

Structure:

src/services/
├── addonService.ts    # Addon operations
├── commentService.ts  # Comment management
├── eNodeService.ts    # Project structure
├── excelService.ts    # Import/export logic
├── historyService.ts  # Change tracking
├── inviteService.ts   # User invitations
├── issueService.ts    # Work item logic
├── linkService.ts     # Dependency management
├── markerService.ts   # Visual indicators
├── peopleService.ts   # User management
├── reminderService.ts # Notification logic
├── reportService.ts   # Analytics generation
├── templateService.ts # Workflow templates
├── typesenseService.ts # Search operations
└── viewService.ts     # Custom views

Key Features:

  • Business rule enforcement
  • Data validation
  • Workflow management
  • Integration logic
  • Error handling

3. Data Access Layer (Prisma)

Purpose: Database operations and data persistence

Structure:

prisma/
├── schema.prisma      # Database schema
├── migrations/        # Database migrations
└── timescale/         # TimescaleDB schema

Key Features:

  • Type-safe database queries
  • Migration management
  • Connection pooling
  • Transaction support
  • Query optimization

4. Infrastructure Layer

Purpose: Cross-cutting concerns and external services

Structure:

infra/
├── bootstrap/
│   └── init.ts        # Application initialization
├── eventBus/
│   ├── EventBus.ts    # Event system interface
│   ├── InMemoryEventBus.ts # In-memory implementation
│   └── NotifyNovu.ts  # Notification service
├── prisma/
│   ├── prismaClient.ts # Database client
│   └── prismaFunction.ts # Database functions
└── services/
    ├── MqService.ts   # Message queue
    ├── NotificationService.ts # Notifications
    ├── SyncerClient.ts # Data sync
    ├── WebsocketService.ts # Real-time
    └── Worker.ts      # Background jobs

API Design Principles

RESTful Design

  • Resource-based URLs: /enodes, /issues, /people
  • HTTP Methods: GET, POST, PUT, DELETE, PATCH
  • Status Codes: Proper HTTP response codes
  • Content Types: JSON request/response format

Request Validation

typescript
// Example with Zod validation
const createIssueSchema = z.object({
  title: z.string().min(1),
  type: z.enum(['task', 'bug', 'story']),
  enode_id: z.string().uuid(),
  effort: z.number().positive().optional()
});

app.post('/issues', async (c) => {
  const data = createIssueSchema.parse(await c.req.json());
  // Process validated data
});

Response Format

typescript
// Standard response structure
interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: string;
  message?: string;
}

Authentication & Authorization

Casdoor Integration

  • Single Sign-On: Centralized authentication
  • JWT Tokens: Secure session management
  • Role-based Access: Granular permissions
  • Multi-tenant: Organization isolation

Permission System

typescript
// Permission middleware example
app.use('/enodes/*', async (c, next) => {
  const token = c.req.header('Authorization');
  const user = await validateToken(token);
  const permissions = await getUserPermissions(user.id, 'enode');
  
  if (!hasPermission(permissions, c.req.method, c.req.path)) {
    return c.json({ error: 'Insufficient permissions' }, 403);
  }
  
  await next();
});

Data Synchronization

Real-time Updates

  • WebSocket Service: Live collaboration
  • Event Bus: Internal event system
  • Syncer Integration: External data sync
  • Notification Service: User alerts

Change Tracking

typescript
// History service example
export class HistoryService {
  async trackChange(issueId: string, userId: string, changes: any) {
    await this.prisma.history.create({
      data: {
        issue_id: issueId,
        owner_id: userId,
        patch: changes,
        type: 'update',
        type_event: 'issue_modified'
      }
    });
  }
}

Performance Optimization

Caching Strategy

  • Redis Caching: Frequently accessed data
  • Query Optimization: Database index usage
  • Connection Pooling: Efficient database connections
  • Background Processing: Async job handling

Rate Limiting

typescript
// Rate limiting middleware
app.use('*', rateLimiter({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP'
}));

Error Handling

Global Error Handler

typescript
app.onError((err, c) => {
  console.error('Error:', err);
  
  if (err instanceof Prisma.PrismaClientKnownRequestError) {
    return c.json({ error: 'Database error', details: err.message }, 500);
  }
  
  if (err instanceof ZodError) {
    return c.json({ error: 'Validation error', details: err.errors }, 400);
  }
  
  return c.json({ error: 'Internal server error' }, 500);
});

Validation Errors

  • Input Validation: Zod schema validation
  • Business Rule Validation: Service layer validation
  • Database Constraint Validation: Prisma error handling
  • Custom Validation: Domain-specific rules

Monitoring & Observability

Logging

  • Structured Logging: JSON format logs
  • Log Levels: Debug, Info, Warn, Error
  • Context Information: Request ID, user, timestamp
  • Performance Metrics: Response time, throughput

Health Checks

typescript
app.get('/health', async (c) => {
  try {
    await prisma.$queryRaw`SELECT 1`;
    return c.json({ status: 'healthy', timestamp: new Date().toISOString() });
  } catch (error) {
    return c.json({ status: 'unhealthy', error: error.message }, 500);
  }
});

Metrics Collection

  • Response Times: API endpoint performance
  • Error Rates: Failure monitoring
  • Database Performance: Query execution times
  • Resource Usage: Memory, CPU utilization

Security Features

Input Sanitization

  • SQL Injection Prevention: Prisma ORM protection
  • XSS Prevention: Output encoding
  • CSRF Protection: Token validation
  • Path Traversal: URL validation

Data Protection

  • Encryption: Sensitive data encryption
  • Access Logging: Complete audit trail
  • Data Masking: PII protection
  • Secure Headers: Security header implementation

Testing Strategy

Unit Testing

  • Service Layer: Business logic testing
  • Utility Functions: Helper function testing
  • Validation: Schema validation testing
  • Mocking: External service mocking

Integration Testing

  • API Endpoints: End-to-end testing
  • Database Operations: Data persistence testing
  • Authentication: Security testing
  • Performance: Load testing

Deployment & DevOps

Containerization

  • Docker: Application containerization
  • Docker Compose: Local development
  • Multi-stage Builds: Production optimization
  • Health Checks: Container health monitoring

Environment Management

  • Configuration: Environment-specific settings
  • Secrets: Secure credential management
  • Feature Flags: Runtime configuration
  • Monitoring: Production monitoring setup

Future Enhancements

Planned Features

  • GraphQL API: Alternative query interface
  • Event Sourcing: Enhanced audit capabilities
  • Microservices: Service decomposition
  • Kubernetes: Container orchestration

Performance Improvements

  • Database Sharding: Horizontal scaling
  • CDN Integration: Content delivery optimization
  • Advanced Caching: Multi-level caching
  • Load Balancing: Traffic distribution