feat: move the terminal fully into the ssh-terminal plugin (B9)

This commit is contained in:
LukeGus committed 2026-09-23 21:41:22 -05:00
1 parent 535126fd1b
commit 79d77678c9
309 files changed
+41789 -14958

No files matched your search

@@ -1,160 +0,0 @@
import { and, desc, eq, inArray, sql } from "drizzle-orm";
import { commandHistory } from "../db/schema.js";
import type { DatabaseContext } from "./database-context.js";
import { rowsAffected } from "./mutation-result.js";
import { insertReturning } from "./returning.js";
export type CommandHistoryRecord = typeof commandHistory.$inferSelect;
export class CommandHistoryRepository {
constructor(
private readonly context: DatabaseContext,
private readonly onWrite?: () => void | Promise<void>,
) {}
async create(
userId: string,
hostId: number,
command: string,
executedAt = new Date().toISOString(),
): Promise<CommandHistoryRecord> {
const [created] = await insertReturning(this.context, commandHistory, {
userId,
hostId,
command,
executedAt,
});
await this.afterWrite();
return created;
}
async listUniqueCommandsForHost(
userId: string,
hostId: number,
limit = 500,
): Promise<string[]> {
const rows = await this.context.drizzle
.select({
command: commandHistory.command,
maxExecutedAt: sql<number>`MAX(${commandHistory.executedAt})`,
})
.from(commandHistory)
.where(
and(
eq(commandHistory.userId, userId),
eq(commandHistory.hostId, hostId),
),
)
.groupBy(commandHistory.command)
.orderBy(desc(sql`MAX(${commandHistory.executedAt})`))
.limit(limit);
return rows.map((row) => row.command);
}
async listCommandsForHost(
userId: string,
hostId: number,
limit = 200,
): Promise<string[]> {
const rows = await this.context.drizzle
.select({
id: commandHistory.id,
command: commandHistory.command,
})
.from(commandHistory)
.where(
and(
eq(commandHistory.userId, userId),
eq(commandHistory.hostId, hostId),
),
)
.orderBy(desc(commandHistory.executedAt))
.limit(limit);
return rows.map((row) => row.command);
}
async deleteCommandForHost(
userId: string,
hostId: number,
command: string,
): Promise<number> {
const result = await this.context.drizzle
.delete(commandHistory)
.where(
and(
eq(commandHistory.userId, userId),
eq(commandHistory.hostId, hostId),
eq(commandHistory.command, command),
),
);
if (rowsAffected(result) > 0) {
await this.afterWrite();
}
return rowsAffected(result);
}
async deleteByUserAndHost(userId: string, hostId: number): Promise<number> {
const result = await this.context.drizzle
.delete(commandHistory)
.where(
and(
eq(commandHistory.userId, userId),
eq(commandHistory.hostId, hostId),
),
);
if (rowsAffected(result) > 0) {
await this.afterWrite();
}
return rowsAffected(result);
}
async deleteByHostId(hostId: number): Promise<number> {
const result = await this.context.drizzle
.delete(commandHistory)
.where(eq(commandHistory.hostId, hostId));
if (rowsAffected(result) > 0) {
await this.afterWrite();
}
return rowsAffected(result);
}
async deleteByHostIds(hostIds: number[]): Promise<number> {
if (hostIds.length === 0) {
return 0;
}
const result = await this.context.drizzle
.delete(commandHistory)
.where(inArray(commandHistory.hostId, hostIds));
if (rowsAffected(result) > 0) {
await this.afterWrite();
}
return rowsAffected(result);
}
async deleteByUserId(userId: string): Promise<number> {
const result = await this.context.drizzle
.delete(commandHistory)
.where(eq(commandHistory.userId, userId));
if (rowsAffected(result) > 0) {
await this.afterWrite();
}
return rowsAffected(result);
}
private async afterWrite(): Promise<void> {
await this.onWrite?.();
}
}
@@ -9,7 +9,6 @@ import { NotificationChannelRepository } from "./notification-channel-repository
import { AutomationRepository } from "./automation-repository.js";
import { ApiKeyRepository } from "./api-key-repository.js";
import { AuditLogRepository } from "./audit-log-repository.js";
import { CommandHistoryRepository } from "./command-history-repository.js";
import { CredentialRepository } from "./credential-repository.js";
import { DashboardServiceLinkRepository } from "./dashboard-service-link-repository.js";
import { DismissedAlertRepository } from "./dismissed-alert-repository.js";
@@ -184,13 +183,6 @@ export function createCurrentAuditLogRepository(): AuditLogRepository {
);
}
export function createCurrentCommandHistoryRepository(): CommandHistoryRepository {
return new CommandHistoryRepository(
createCurrentRepositoryContext(),
createCurrentRepositoryWriteHook("command_history_repository_write"),
);
}
export function createCurrentCredentialRepository(): CredentialRepository {
return new CredentialRepository(
createCurrentRepositoryContext(),