Skip to content

BoardsService

reference
2 min readUpdated

Kind: Service

Source: atloria-monorepo/apps/api/src/boards/boards.service.ts

BoardsService encapsulates backend business logic for managing boards and their columns in the Atloria API. It provides CRUD operations, restore support, and column-specific workflows such as adding, updating, reordering, and deleting columns while coordinating persistence and validation for board-related endpoints.

Methods

MethodSignatureReturnsDescription
listlist(projectId: string, user: JwtPayload)unknownList all (non-deleted) boards for a project
createcreate(projectId: string, dto: CreateBoardDto, user: JwtPayload)unknownCreate a new board (optionally with template columns + seed cards)
getOnegetOne(projectId: string, boardId: string, user: JwtPayload, includeCards: unknown)unknownGet a board with all columns and (optionally) cards
updateupdate(projectId: string, boardId: string, dto: UpdateBoardDto, user: JwtPayload)unknownUpdate board metadata
removeremove(projectId: string, boardId: string, user: JwtPayload)unknownSoft-delete a board (default board cannot be deleted)
restorerestore(projectId: string, boardId: string, user: JwtPayload)unknownRestore a soft-deleted board (within the 30-day window)
addColumnaddColumn(projectId: string, boardId: string, dto: CreateColumnDto, user: JwtPayload)unknown
updateColumnupdateColumn(projectId: string, boardId: string, columnId: string, dto: UpdateColumnDto, user: JwtPayload)unknown
reorderColumnsreorderColumns(projectId: string, boardId: string, dto: ReorderColumnsDto, user: JwtPayload)unknown
deleteColumn`deleteColumn(projectId: string, boardId: string, columnId: string, moveCardsTo: stringundefined, user: JwtPayload)`unknown
listCards`listCards(projectId: string, boardId: string, since: Dateundefined, user: JwtPayload)`unknown
addCardsaddCards(projectId: string, boardId: string, dto: AddCardsDto, user: JwtPayload)unknown
moveCardmoveCard(projectId: string, boardId: string, cardId: string, dto: MoveCardDto, user: JwtPayload)unknown
removeCardremoveCard(projectId: string, boardId: string, cardId: string, user: JwtPayload)unknown
getBoardsForIssuegetBoardsForIssue(projectId: string, issueId: string, user: JwtPayload)unknownFind boards an issue is on (used by issue detail page sidebar)

Dependencies

  • PrismaService
  • IssuesService

Where it refuses work

  • BoardsService stops the work with NotFoundException when !board — “Board not found”, in 3 places.
  • BoardsService stops the work with NotFoundException when !card — “Card not found”, in 2 places.
  • BoardsService stops the work with NotFoundException when !project — “Project not found”.
  • BoardsService stops the work with ForbiddenException when project.organizationId !== user.organizationId — “You do not have access to this project”.
  • BoardsService stops the work with NotFoundException when !board — “Deleted board not found”.
  • BoardsService stops the work with BadRequestException when dto.columnIds.length !== cols.length || !dto.columnIds.every((id) => existingIds.has(id)) — “columnIds must list every existing column id exactly once”.

Diagram

mermaid
sequenceDiagram
  participant Client
  participant Controller as BoardsController
  participant Service as BoardsService
  participant Database as Persistence Layer

  Client->>Controller: Create or update board request
  Controller->>Service: create() / update()
  Service->>Database: Validate and persist board data
  Database-->>Service: Board result
  Service-->>Controller: Board response
  Controller-->>Client: HTTP response

  Client->>Controller: Reorder board columns
  Controller->>Service: reorderColumns()
  Service->>Database: Update column ordering
  Database-->>Service: Updated board columns
  Service-->>Controller: Reordered columns
  Controller-->>Client: HTTP response

Usage

ts
import { Injectable } from '@nestjs/common';
import { BoardsService } from './boards.service';

@Injectable()
export class BoardWorkflowService {
  constructor(private readonly boardsService: BoardsService) {}

  async createBoardWithFirstColumn(userId: string) {
    const board = await this.boardsService.create({
      name: 'Product Roadmap',
      ownerId: userId,
    });

    await this.boardsService.addColumn(board.id, {
      name: 'Backlog',
      order: 0,
    });

    return this.boardsService.getOne(board.id);
  }

  async moveColumns(boardId: string, columnIds: string[]) {
    return this.boardsService.reorderColumns(boardId, columnIds);
  }
}

AI Coding Instructions

  • Keep board and column mutations in BoardsService; controllers should only handle request parsing, guards, and response mapping.
  • Use getOne() before dependent operations when the workflow requires verifying that a board exists or is accessible.
  • Preserve column ordering invariants when implementing addColumn(), updateColumn(), reorderColumns(), or deleteColumn().
  • Treat remove() and restore() as lifecycle operations; do not permanently delete related data unless the intended deletion policy explicitly requires it.
  • Ensure authorization and tenant/workspace ownership checks are consistently applied to list, read, update, and column-management operations.

Relationships

  • DEPENDS_ON → PrismaService
  • DEPENDS_ON → IssuesService

Referenced By

  • BoardsController (DEPENDS_ON)
  • BoardsModule (MODULE_PROVIDES)
  • BoardsModule (MODULE_EXPORTS)

Was this page helpful?

Download as PDF