Docs /api-reference/trpc-routers

tRPC Routers API Reference

Complete API reference for all tRPC routers in the Izri platform.

📋 Overview

The tRPC API provides type-safe client-server communication with automatic TypeScript inference. All endpoints require authentication unless marked as publicProcedure.

Base URL: /trpc

Router Structure:

  • auth.* - Authentication & session management
  • projects.* - Project CRUD operations
  • organizations.* - Organization management
  • analysis.* - Repository analysis
  • health - Health check

🔐 auth Router

Authentication, session management, and user profiles.

auth.getSession

Get current user session information.

Type: Query (public)

Input: None

Output:

{
  isAuthenticated: boolean
  session: {
    id: string
    userId: string
    expiresAt: Date
    createdAt: Date
  } | null
  user: {
    id: string
    email: string
    name: string
    avatar?: string
    createdAt: Date
  } | null
}

Example:

const { data } = await trpc.auth.getSession.useQuery()
if (data?.isAuthenticated) {
  console.log('Logged in as:', data.user?.email)
}

auth.getProfile

Get current user profile details.

Type: Query (protected)

Input: None

Output:

{
  id: string
  email: string
  name: string
  avatar?: string
  emailVerified: boolean
  createdAt: Date
  updatedAt: Date
}

Example:

const { data: profile } = await trpc.auth.getProfile.useQuery()

Errors:

  • User not authenticated - No active session

auth.updateProfile

Update current user's profile information.

Type: Mutation (protected)

Input:

{
  name?: string
  avatar?: string  // URL
}

Output: Updated user object

Example:

const { mutate } = trpc.auth.updateProfile.useMutation()
mutate({
  name: 'John Doe',
  avatar: 'https://example.com/avatar.jpg'
})

auth.listSessions

List all active sessions for current user.

Type: Query (protected)

Input: None

Output:

Array<{
  id: string
  userId: string
  expiresAt: Date
  createdAt: Date
  ipAddress?: string
  userAgent?: string
}>

Example:

const { data: sessions } = await trpc.auth.listSessions.useQuery()

auth.invalidateSession

Logout (revoke current session).

Type: Mutation (protected)

Input: None

Output:

{ success: boolean }

Example:

const { mutate: logout } = trpc.auth.invalidateSession.useMutation()
logout()

auth.revokeSession

Revoke a specific session.

Type: Mutation (protected)

Input:

{
  sessionToken: string
}

Output:

{ success: boolean }

Example:

const { mutate } = trpc.auth.revokeSession.useMutation()
mutate({ sessionToken: 'session_abc123' })

auth.revokeOtherSessions

Revoke all sessions except the current one.

Type: Mutation (protected)

Input: None

Output:

{ success: boolean }

Example:

const { mutate } = trpc.auth.revokeOtherSessions.useMutation()
mutate()

auth.getAuditLogs

Get authentication audit logs for current user.

Type: Query (protected)

Input:

{
  limit?: number   // 1-100, default: 50
  offset?: number  // default: 0
}

Output:

Array<{
  id: string
  userId: string
  action: string
  ipAddress?: string
  userAgent?: string
  metadata?: Record<string, any>
  createdAt: Date
}>

Example:

const { data: logs } = await trpc.auth.getAuditLogs.useQuery({
  limit: 20,
  offset: 0
})

📁 projects Router

Project management and CRUD operations.

projects.getProjects

Get all projects for current user.

Type: Query (public)

Input:

{
  userEmail: string  // email format
}

Output:

{
  projects: Array<{
    id: string
    name: string
    description?: string
    repository: string
    branch: string
    language: string
    framework?: string
    userId: string
    createdAt: Date
    updatedAt: Date
    testRuns: Array<{
      id: string
      projectId: string
      status: 'pending' | 'running' | 'completed' | 'failed'
      totalTests: number
      passedTests: number
      failedTests: number
      createdAt: Date
    }>
  }>
}

Example:

const { data } = await trpc.projects.getProjects.useQuery({
  userEmail: 'user@example.com'
})

Errors:

  • User not found - Email doesn't match any user

projects.getProject

Get single project by ID with test runs and settings.

Type: Query (protected)

Input:

{
  projectId: string
  userEmail: string
}

Output:

{
  project: {
    id: string
    name: string
    description?: string
    repository: string
    branch: string
    language: string
    framework?: string
    userId: string
    createdAt: Date
    updatedAt: Date
    testRuns: TestRun[]
    settings: {
      id: string
      projectId: string
      autoRunTests: boolean
      enableUnitTests: boolean
      enableIntegrationTests: boolean
      enableE2ETests: boolean
      notifyOnFailure: boolean
    } | null
  }
}

Example:

const { data } = await trpc.projects.getProject.useQuery({
  projectId: 'proj_123',
  userEmail: 'user@example.com'
})

Errors:

  • User not found
  • Project not found - Project doesn't exist or user doesn't own it

projects.createProject

Create a new project.

Type: Mutation (protected)

Input:

{
  name: string             // min 1 char
  repository: string       // min 1 char
  userEmail: string        // email format
  description?: string
  branch?: string          // default: 'main'
  language?: string        // default: 'unknown'
  framework?: string
}

Output:

{
  project: {
    id: string
    name: string
    repository: string
    // ... other fields
    testRuns: []
  }
}

Example:

const { mutate } = trpc.projects.createProject.useMutation()
mutate({
  name: 'My App',
  repository: 'https://github.com/user/repo',
  userEmail: 'user@example.com',
  branch: 'main',
  language: 'typescript',
  framework: 'react'
})

Errors:

  • User not found
  • Project with this repository already exists - Duplicate repository URL for user

Side Effects:

  • Creates default project settings
  • Sets autoRunTests: false, notifyOnFailure: true, enables all test types

projects.updateProject

Update existing project.

Type: Mutation (protected)

Input:

{
  projectId: string
  userEmail: string
  name?: string
  description?: string
  branch?: string
  language?: string
  framework?: string
}

Output:

{
  project: {
    // Updated project with settings and testRuns
  }
}

Example:

const { mutate } = trpc.projects.updateProject.useMutation()
mutate({
  projectId: 'proj_123',
  userEmail: 'user@example.com',
  name: 'Updated Name',
  description: 'New description'
})

Errors:

  • User not found
  • Project not found

Note: Cannot update id, repository, userId, or createdAt


projects.deleteProject

Delete a project and all associated data.

Type: Mutation (protected)

Input:

{
  projectId: string
  userEmail: string
}

Output:

{
  message: 'Project deleted successfully'
}

Example:

const { mutate } = trpc.projects.deleteProject.useMutation()
mutate({
  projectId: 'proj_123',
  userEmail: 'user@example.com'
})

Errors:

  • User not found
  • Project not found

Side Effects (Cascade):

  • Deletes project settings
  • Deletes all test runs
  • Deletes all analyses
  • Cannot be undone

projects.getProjectAnalyses

Get all analyses for a project.

Type: Query (protected)

Input:

{
  projectId: string
  userEmail: string
}

Output:

{
  analyses: Array<{
    id: string
    projectId: string
    repoUrl: string
    branch: string
    commitSha?: string
    analysis: object  // Full analysis JSONB
    createdAt: Date
  }>
}

Example:

const { data } = await trpc.projects.getProjectAnalyses.useQuery({
  projectId: 'proj_123',
  userEmail: 'user@example.com'
})

Errors:

  • User not found
  • Project not found or access denied

projects.getLatestProjectAnalysis

Get most recent analysis for a project.

Type: Query (protected)

Input:

{
  projectId: string
  userEmail: string
}

Output:

{
  analysis: {
    id: string
    projectId: string
    repoUrl: string
    branch: string
    commitSha?: string
    analysis: {
      files: Array<{
        path: string
        language: string
        size: number
        content?: string
      }>
      languages: Record<string, number>
      frameworks: string[]
      dependencies: Record<string, string>
      // ... full analysis structure
    }
    createdAt: Date
  } | null
}

Example:

const { data } = await trpc.projects.getLatestProjectAnalysis.useQuery({
  projectId: 'proj_123',
  userEmail: 'user@example.com'
})

🏢 organizations Router

Multi-tenancy and organization management.

organizations.list

List all organizations for current user.

Type: Query (protected)

Input:

{
  userEmail: string
}

Output:

{
  organizations: Array<{
    id: string
    name: string
    slug: string
    description?: string
    role: 'OWNER' | 'ADMIN' | 'MEMBER' | 'VIEWER'
    createdAt: Date
    updatedAt: Date
  }>
}

Example:

const { data } = await trpc.organizations.list.useQuery({
  userEmail: 'user@example.com'
})

organizations.create

Create a new organization.

Type: Mutation (protected)

Input:

{
  name: string           // min 1 char
  slug: string           // lowercase, numbers, hyphens only
  userEmail: string
  description?: string
}

Output:

{
  organization: {
    id: string
    name: string
    slug: string
    description?: string
    createdAt: Date
    updatedAt: Date
  }
}

Example:

const { mutate } = trpc.organizations.create.useMutation()
mutate({
  name: 'Acme Corp',
  slug: 'acme-corp',
  userEmail: 'user@example.com',
  description: 'Our organization'
})

Errors:

  • User not found
  • An organization with this slug already exists
  • Validation error if slug format is invalid

Side Effects:

  • Creator automatically becomes OWNER
  • Slug must be globally unique

organizations.getBySlug

Get organization details by slug.

Type: Query (protected)

Input:

{
  slug: string
  userEmail: string
}

Output:

{
  organization: {
    id: string
    name: string
    slug: string
    description?: string
    role: 'OWNER' | 'ADMIN' | 'MEMBER' | 'VIEWER'  // User's role
    createdAt: Date
    updatedAt: Date
  }
}

Errors:

  • User not found
  • Organization not found
  • Access denied - User is not a member

organizations.delete

Delete an organization.

Type: Mutation (protected)

Input:

{
  organizationId: string
  userEmail: string
}

Output:

{
  message: 'Organization deleted successfully'
}

Errors:

  • User not found
  • Only organization owners can delete organizations

Permissions: OWNER only

Side Effects:

  • Deletes all members (cascade)
  • Cannot be undone

organizations.getMembers

List all members of an organization.

Type: Query (protected)

Input:

{
  organizationId: string
  userEmail: string
}

Output:

{
  members: Array<{
    id: string           // membership ID
    userId: string
    email: string
    name: string
    role: 'OWNER' | 'ADMIN' | 'MEMBER' | 'VIEWER'
    createdAt: Date
  }>
}

Example:

const { data } = await trpc.organizations.getMembers.useQuery({
  organizationId: 'org_123',
  userEmail: 'user@example.com'
})

Errors:

  • User not found
  • Access denied - User is not a member

Permissions: Any member can view


organizations.inviteMember

Invite a user to join the organization.

Type: Mutation (protected)

Input:

{
  organizationId: string
  userEmail: string              // Inviter
  userToInviteEmail: string      // Invitee
  role?: 'OWNER' | 'ADMIN' | 'MEMBER' | 'VIEWER'  // default: 'MEMBER'
}

Output:

{
  member: {
    id: string
    organizationId: string
    userId: string
    email: string
    name: string
    role: string
    createdAt: Date
  }
}

Example:

const { mutate } = trpc.organizations.inviteMember.useMutation()
mutate({
  organizationId: 'org_123',
  userEmail: 'admin@example.com',
  userToInviteEmail: 'newuser@example.com',
  role: 'MEMBER'
})

Errors:

  • User not found (inviter or invitee)
  • Only organization owners and admins can invite members
  • User is already a member of this organization

Permissions: OWNER and ADMIN


organizations.updateMemberRole

Change a member's role in the organization.

Type: Mutation (protected)

Input:

{
  organizationId: string
  membershipId: string
  userEmail: string
  newRole: 'OWNER' | 'ADMIN' | 'MEMBER' | 'VIEWER'
}

Output:

{
  member: {
    id: string
    role: string
    // ... other fields
  }
}

Errors:

  • User not found
  • Only organization owners can change member roles
  • Cannot remove the last owner of an organization
  • Cannot change your own role (prevents lockout)

Permissions: OWNER only


organizations.removeMember

Remove a member from the organization.

Type: Mutation (protected)

Input:

{
  organizationId: string
  membershipId: string
  userEmail: string
}

Output:

{
  message: 'Member removed successfully'
}

Errors:

  • User not found
  • Only organization owners and admins can remove members
  • Member not found
  • Cannot remove the last owner of an organization

Permissions: OWNER and ADMIN

Side Effects:

  • Removes access to all organization projects
  • User can be re-invited later

🔬 analysis Router

Repository analysis operations.

analysis.analyzeRepository

Analyze a GitHub repository and store results.

Type: Mutation (protected)

Input:

{
  projectId: string
  repoUrl: string              // GitHub URL
  userEmail: string
  branch?: string              // default: 'main'
  githubToken?: string         // For private repos
  options?: {
    maxFiles?: number          // default: 1000
    maxFileSizeBytes?: number  // default: 500KB
    includeHashes?: boolean    // default: false
  }
}

Output:

{
  success: boolean
  message: string
  analysis: {
    id: string
    projectId: string
    repoUrl: string
    branch: string
    commitSha?: string
    analysis: {
      files: Array<{
        path: string
        language: string
        size: number
        extension: string
        hash?: string
        content?: string
      }>
      languages: Record<string, number>  // { "TypeScript": 150, "JavaScript": 50 }
      frameworks: string[]               // ["react", "vite"]
      dependencies: Record<string, string>
      testFiles: string[]
      testCandidates: Array<{
        path: string
        priority: number
        reason: string
      }>
      structure: {
        directories: number
        files: number
        totalSize: number
      }
      commitSha: string
      analyzedAt: string
    }
    createdAt: Date
  }
}

Example:

const { mutate, isLoading } = trpc.analysis.analyzeRepository.useMutation()
mutate({
  projectId: 'proj_123',
  repoUrl: 'https://github.com/user/repo',
  userEmail: 'user@example.com',
  branch: 'main',
  options: {
    maxFiles: 500,
    includeHashes: true
  }
})

Errors:

  • User not found
  • Project not found or access denied
  • Analysis failed: <error message> - Repository clone/parse errors

Side Effects:

  • Clones repository to temporary directory
  • Analyzes file structure, languages, frameworks
  • Stores analysis in database (upserts by projectId + commitSha)
  • Cleans up temporary files

Performance:

  • Large repositories may take 10-60 seconds
  • Consider running in background job for very large repos

🏥 health

Simple health check endpoint.

Type: Query (public)

Input: None

Output:

{ ok: true }

Example:

const { data } = await trpc.health.useQuery()
// { ok: true }

🔧 Type Inference

TypeScript types are automatically inferred from the router:

import type { AppRouter, AppRouterInputs, AppRouterOutputs } from '@izri/trpc'

// Input types
type CreateProjectInput = AppRouterInputs['projects']['createProject']
type GetProjectInput = AppRouterInputs['projects']['getProject']

// Output types
type ProjectsOutput = AppRouterOutputs['projects']['getProjects']
type SessionOutput = AppRouterOutputs['auth']['getSession']

// Router type for custom hooks
type Router = AppRouter

🚨 Error Handling

All errors are thrown as TRPCError with descriptive messages:

// Client-side error handling
const { mutate } = trpc.projects.createProject.useMutation({
  onError: (error) => {
    console.error(error.message)
    // "User not found"
    // "Project with this repository already exists"
  },
  onSuccess: (data) => {
    console.log('Project created:', data.project.id)
  }
})

Common error messages:

  • User not found - Authentication/authorization issue
  • Project not found - Resource doesn't exist or no access
  • Access denied - Insufficient permissions
  • Only organization owners can... - Permission denied
  • Validation errors from Zod schemas

See Error Codes for complete reference.


🔗 Related Documentation

Reading this with an agent? /docs/api-reference/trpc-routers.md serves the raw markdown.

All docs