PackagesServer Package

Server Package

Backend services and data layer for the monorepo.

Overview

The packages/server/ directory contains backend services, repositories, and utilities shared across applications.

Location: packages/server/

Sub-packages:

  • @uwdsc/server/core - Shared backend utilities
  • @uwdsc/server/web - Web app backend
  • @uwdsc/server/cxc - CxC app backend

Structure

packages/server/
β”œβ”€β”€ core/              # Shared backend utilities
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ database/     # Supabase client
β”‚   β”‚   β”œβ”€β”€ services/     # Auth, file services
β”‚   β”‚   β”œβ”€β”€ repository/   # Base repository
β”‚   β”‚   β”œβ”€β”€ types/        # TypeScript types
β”‚   β”‚   └── utils/        # Error handling
β”‚   └── package.json
β”œβ”€β”€ web/               # Web app backend
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ db/          # Database migrations (db-mate)
β”‚   β”‚   β”œβ”€β”€ services/     # Business logic
β”‚   β”‚   β”œβ”€β”€ repository/   # Data access
β”‚   β”‚   └── types/        # Types
β”‚   └── package.json
└── cxc/               # CxC app backend
    β”œβ”€β”€ src/
    β”‚   β”œβ”€β”€ db/          # Database migrations (db-mate)
    β”‚   β”œβ”€β”€ services/     # Business logic
    β”‚   β”œβ”€β”€ repository/   # Data access
    β”‚   └── types/        # Types
    └── package.json

Core Package (@uwdsc/server/core)

Shared backend utilities used by both web and cxc backends.

Exports

import { AuthService } from "@uwdsc/server/core/services/authService";
import { FileService } from "@uwdsc/server/core/services/fileService";
import { BaseRepository } from "@uwdsc/server/core/repository/baseRepository";

Services

AuthService - Authentication with Supabase

  • Sign up
  • Sign in
  • User management
  • Session handling

FileService - File upload/storage with Supabase Storage

  • Upload files
  • Get public URLs
  • Delete files

ResumeService - Resume processing

  • Parse resumes
  • Extract data

Repository

BaseRepository - Base class for all repositories

  • pg connection pool access
  • Common database operations
  • Transaction support

Web Package (@uwdsc/server/web)

Backend services specific to the main website.

Exports

import { HealthService } from "@uwdsc/server/web/services/healthService";
import { ProfileService } from "@uwdsc/server/web/services/profileService";
import { ApplicationService } from "@uwdsc/server/web/services/applicationService";

Services

  • HealthService - System health checks
  • ProfileService - User profile management
  • ApplicationService - Membership applications
  • EventService - Event management

Repositories

  • HealthRepository - Health check queries
  • ProfileRepository - Profile data access
  • ApplicationRepository - Application data access
  • EventRepository - Event data access

CxC Package (@uwdsc/server/cxc)

Backend services specific to the CxC AI hackathon app.

Exports

import { ApplicationService } from "@uwdsc/server/cxc/services/applicationService";
import { TeamService } from "@uwdsc/server/cxc/services/teamService";

Services

  • ApplicationService - AI hackathon applications
  • TeamService - Team management
  • EventService - AI hackathon events

Usage

In API Routes

// apps/web/app/api/profile/route.ts
import { NextResponse } from "next/server";
import { ProfileService } from "@uwdsc/server/web/services/profileService";
 
export async function GET() {
  const profileService = new ProfileService();
  const profile = await profileService.getProfile(userId);
  return NextResponse.json(profile);
}

Service Layer

// packages/server/web/src/services/profileService.ts
import { ProfileRepository } from "../repository/profileRepository";
 
export class ProfileService {
  private repository: ProfileRepository;
 
  constructor() {
    this.repository = new ProfileRepository();
  }
 
  async getProfile(userId: string) {
    return await this.repository.findById(userId);
  }
}

Repository Layer

// packages/server/web/src/repository/profileRepository.ts
import { BaseRepository } from "@uwdsc/server/core/repository/baseRepository";
 
export class ProfileRepository extends BaseRepository {
  async findById(userId: string) {
    const result = await this.pool.query(
      "SELECT * FROM users WHERE id = $1",
      [userId]
    );
    return result.rows[0] || null;
  }
}

Database

Migrations (db-mate)

Each app-specific package has its own migration directory:

-- packages/server/web/src/db/migrations/001_create_users_table.up.sql
 
CREATE TABLE IF NOT EXISTS users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email VARCHAR(255) UNIQUE NOT NULL,
  name VARCHAR(255) NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);
 
CREATE INDEX idx_users_email ON users(email);

Migrations are managed with db-mate:

# Create new migration
db-mate new add_user_bio
 
# Apply migrations
db-mate up
 
# Rollback last migration
db-mate down

Supabase

Core package uses Supabase for:

  • Authentication
  • File storage
  • Real-time subscriptions

Best Practices

βœ… Do

  • Use services for business logic
  • Use repositories for data access
  • Extend BaseRepository for common functionality
  • Handle errors appropriately
  • Use TypeScript types
  • Write unit tests

❌ Don’t

  • Put business logic in repositories
  • Access database directly from services
  • Skip error handling
  • Expose internal errors to clients
  • Mix concerns across layers

Next Steps