feat(api): add terminal session persistence with Prisma model and CRUD (#517)
Some checks failed
ci/woodpecker/push/api Pipeline failed
Some checks failed
ci/woodpecker/push/api Pipeline failed
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #517.
This commit is contained in:
96
apps/api/src/terminal/terminal-session.service.ts
Normal file
96
apps/api/src/terminal/terminal-session.service.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* TerminalSessionService
|
||||
*
|
||||
* Manages database persistence for terminal sessions.
|
||||
* Provides CRUD operations on the TerminalSession model,
|
||||
* enabling session tracking, recovery, and workspace-level listing.
|
||||
*
|
||||
* Session lifecycle:
|
||||
* - create: record a new terminal session with ACTIVE status
|
||||
* - findByWorkspace: return all ACTIVE sessions for a workspace
|
||||
* - close: mark a session as CLOSED, set closedAt timestamp
|
||||
* - findById: retrieve a single session by ID
|
||||
*/
|
||||
|
||||
import { Injectable, NotFoundException, Logger } from "@nestjs/common";
|
||||
import { TerminalSessionStatus } from "@prisma/client";
|
||||
import type { TerminalSession } from "@prisma/client";
|
||||
import { PrismaService } from "../prisma/prisma.service";
|
||||
|
||||
@Injectable()
|
||||
export class TerminalSessionService {
|
||||
private readonly logger = new Logger(TerminalSessionService.name);
|
||||
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
/**
|
||||
* Create a new terminal session record in the database.
|
||||
*
|
||||
* @param workspaceId - The workspace this session belongs to
|
||||
* @param name - Optional display name for the session (defaults to "Terminal")
|
||||
* @returns The created TerminalSession record
|
||||
*/
|
||||
async create(workspaceId: string, name?: string): Promise<TerminalSession> {
|
||||
this.logger.log(
|
||||
`Creating terminal session for workspace ${workspaceId}${name !== undefined ? ` (name: ${name})` : ""}`
|
||||
);
|
||||
|
||||
const data: { workspaceId: string; name?: string } = { workspaceId };
|
||||
if (name !== undefined) {
|
||||
data.name = name;
|
||||
}
|
||||
|
||||
return this.prisma.terminalSession.create({ data });
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all ACTIVE terminal sessions for a workspace.
|
||||
*
|
||||
* @param workspaceId - The workspace to query
|
||||
* @returns Array of active TerminalSession records, ordered by creation time (newest first)
|
||||
*/
|
||||
async findByWorkspace(workspaceId: string): Promise<TerminalSession[]> {
|
||||
return this.prisma.terminalSession.findMany({
|
||||
where: {
|
||||
workspaceId,
|
||||
status: TerminalSessionStatus.ACTIVE,
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a terminal session by setting its status to CLOSED and recording closedAt.
|
||||
*
|
||||
* @param id - The session ID to close
|
||||
* @returns The updated TerminalSession record
|
||||
* @throws NotFoundException if the session does not exist
|
||||
*/
|
||||
async close(id: string): Promise<TerminalSession> {
|
||||
const existing = await this.prisma.terminalSession.findUnique({ where: { id } });
|
||||
|
||||
if (!existing) {
|
||||
throw new NotFoundException(`Terminal session ${id} not found`);
|
||||
}
|
||||
|
||||
this.logger.log(`Closing terminal session ${id} (workspace: ${existing.workspaceId})`);
|
||||
|
||||
return this.prisma.terminalSession.update({
|
||||
where: { id },
|
||||
data: {
|
||||
status: TerminalSessionStatus.CLOSED,
|
||||
closedAt: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a terminal session by ID.
|
||||
*
|
||||
* @param id - The session ID to retrieve
|
||||
* @returns The TerminalSession record, or null if not found
|
||||
*/
|
||||
async findById(id: string): Promise<TerminalSession | null> {
|
||||
return this.prisma.terminalSession.findUnique({ where: { id } });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user