refactor(db): collapse repository rollout scaffolding into single factory

Repositories are now the only data path. Replaces the 41 current-*-repository
wrapper files, the DATABASE_LAYER_REPOSITORY_ROLLOUT flag/alias map and the
unused database/runtime adapter with repositories/factory.ts, a plain
DatabaseContext type and an in-memory TestSqliteDatabase test harness.
This commit is contained in:
LukeGus
2026-07-15 23:56:02 -05:00
parent 1e7c9ea53c
commit ef4969dd35
217 changed files with 843 additions and 4297 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
import { createCurrentAlertRepository } from "../database/repositories/current-alert-repository.js";
import { createCurrentAlertRepository } from "../database/repositories/factory.js";
import { statsLogger } from "../utils/logger.js";
import {
sendNotification,
+1 -1
View File
@@ -1,6 +1,6 @@
import type { WebSocket } from "ws";
import { sshLogger, authLogger } from "../utils/logger.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
interface ResolvedCredentials {
username: string;
password?: string;
+3 -3
View File
@@ -63,7 +63,7 @@ describe("expandOidcUsername", () => {
});
it("expands the placeholder with the user's OIDC identifier", async () => {
vi.doMock("../database/repositories/current-user-repository.js", () => ({
vi.doMock("../database/repositories/factory.js", () => ({
createCurrentUserRepository: () => ({
findById: async () => ({ oidcIdentifier: "jdoe" }),
}),
@@ -75,7 +75,7 @@ describe("expandOidcUsername", () => {
});
it("leaves the placeholder as-is when the user has no OIDC identifier", async () => {
vi.doMock("../database/repositories/current-user-repository.js", () => ({
vi.doMock("../database/repositories/factory.js", () => ({
createCurrentUserRepository: () => ({
findById: async () => ({ oidcIdentifier: null }),
}),
@@ -89,7 +89,7 @@ describe("expandOidcUsername", () => {
});
it("returns the username unchanged when the DB lookup throws", async () => {
vi.doMock("../database/repositories/current-user-repository.js", () => ({
vi.doMock("../database/repositories/factory.js", () => ({
createCurrentUserRepository: () => {
throw new Error("DB unavailable");
},
+1 -1
View File
@@ -49,7 +49,7 @@ export async function expandOidcUsername(
try {
const { createCurrentUserRepository } =
await import("../database/repositories/current-user-repository.js");
await import("../database/repositories/factory.js");
const user = await createCurrentUserRepository().findById(userId);
const oidcIdentifier = user?.oidcIdentifier;
if (!oidcIdentifier) return username;
+1 -1
View File
@@ -2,7 +2,7 @@ import { Client as SSHClient } from "ssh2";
import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js";
import { WebSocketServer, WebSocket } from "ws";
import { AuthManager } from "../utils/auth-manager.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
import { systemLogger } from "../utils/logger.js";
import type { SSHHost } from "../../types/index.js";
import { applyAgentAuth } from "./terminal-auth-helpers.js";
+1 -1
View File
@@ -4,7 +4,7 @@ import cookieParser from "cookie-parser";
import axios from "axios";
import { Client as SSHClient } from "ssh2";
import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
import { fileLogger } from "../utils/logger.js";
import { AuthManager } from "../utils/auth-manager.js";
import type { AuthenticatedRequest, ProxyNode } from "../../types/index.js";
+1 -1
View File
@@ -1,5 +1,5 @@
import type { WebSocket } from "ws";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
import { sshLogger } from "../utils/logger.js";
interface HostKeyVerificationData {
@@ -1,6 +1,6 @@
import type { Express, RequestHandler } from "express";
import type { AuthenticatedRequest } from "../../types/index.js";
import { createCurrentHostMetricsHistoryRepository } from "../database/repositories/current-host-metrics-history-repository.js";
import { createCurrentHostMetricsHistoryRepository } from "../database/repositories/factory.js";
import { statsLogger } from "../utils/logger.js";
type HistoryRoutesDeps = {
+1 -1
View File
@@ -5,7 +5,7 @@ import {
createSocks5Connection,
type SOCKS5Config,
} from "../utils/socks5-helper.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
import { SSHHostKeyVerifier } from "./host-key-verifier.js";
import { getJumpHostSocks5Config } from "./jump-host-proxy.js";
import { applyAgentAuth } from "./terminal-auth-helpers.js";
@@ -1,6 +1,6 @@
import type { Express, RequestHandler } from "express";
import type { AuthenticatedRequest } from "../../types/index.js";
import { createCurrentHostMetricsPreferenceRepository } from "../database/repositories/current-host-metrics-preference-repository.js";
import { createCurrentHostMetricsPreferenceRepository } from "../database/repositories/factory.js";
import { statsLogger } from "../utils/logger.js";
import {
deriveEnabledWidgets,
@@ -1,6 +1,6 @@
import type { Express, RequestHandler } from "express";
import { statsLogger } from "../utils/logger.js";
import { createCurrentSettingsRepository } from "../database/repositories/current-settings-repository.js";
import { createCurrentSettingsRepository } from "../database/repositories/factory.js";
type HostMetricsSettingsConfig = {
statusCheckInterval: number;
+5 -3
View File
@@ -8,9 +8,11 @@ import {
pickResolvedPassword,
pickResolvedUsername,
} from "./credential-username.js";
import { getCurrentSettingValue } from "../database/repositories/current-settings-repository.js";
import { createCurrentHostMetricsHistoryRepository } from "../database/repositories/current-host-metrics-history-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import {
getCurrentSettingValue,
createCurrentHostMetricsHistoryRepository,
createCurrentHostResolutionRepository,
} from "../database/repositories/factory.js";
import { statsLogger } from "../utils/logger.js";
import { DataCrypto } from "../utils/data-crypto.js";
import { AuthManager } from "../utils/auth-manager.js";
+4 -2
View File
@@ -1,5 +1,7 @@
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentVaultProfileRepository } from "../database/repositories/current-vault-profile-repository.js";
import {
createCurrentHostResolutionRepository,
createCurrentVaultProfileRepository,
} from "../database/repositories/factory.js";
import { logger } from "../utils/logger.js";
import {
pickResolvedPassword,
+1 -1
View File
@@ -1,5 +1,5 @@
import { Client as SSHClient } from "ssh2";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
import { fileLogger } from "../utils/logger.js";
import {
createSocks5Connection,
+1 -1
View File
@@ -2,7 +2,7 @@ import type { Express } from "express";
import type { Client } from "ssh2";
import type { AuthenticatedRequest } from "../../../types/index.js";
import { execCommand } from "../widgets/common-utils.js";
import { createCurrentHostHealthRepository } from "../../database/repositories/current-host-health-repository.js";
import { createCurrentHostHealthRepository } from "../../database/repositories/factory.js";
import { managerHandler, ManagerInputError } from "./route-helpers.js";
import { shellSingleQuote } from "./exec-elevated.js";
import { isValidPort } from "./validation.js";
+1 -1
View File
@@ -3,7 +3,7 @@ import { randomUUID } from "crypto";
import { WebSocket } from "ws";
import { OPKSSHBinaryManager } from "../utils/opkssh-binary-manager.js";
import { sshLogger } from "../utils/logger.js";
import { createCurrentOpksshTokenRepository } from "../database/repositories/current-opkssh-token-repository.js";
import { createCurrentOpksshTokenRepository } from "../database/repositories/factory.js";
import { UserCrypto } from "../utils/user-crypto.js";
import { FieldCrypto } from "../utils/field-crypto.js";
import { promises as fs } from "fs";
+1 -1
View File
@@ -1,5 +1,5 @@
import ssh2Pkg, { type Client as SSHClientType } from "ssh2";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js";
import { sshLogger } from "../utils/logger.js";
import {
@@ -8,15 +8,12 @@ vi.mock("../database/db/index.js", () => ({
getDb: () => ({}),
}));
vi.mock(
"../database/repositories/current-session-recording-repository.js",
() => ({
createCurrentSessionRecordingRepository: () => ({
create: mockCreate,
updateEnded: mockUpdateEnded,
}),
vi.mock("../database/repositories/factory.js", () => ({
createCurrentSessionRecordingRepository: () => ({
create: mockCreate,
updateEnded: mockUpdateEnded,
}),
);
}));
vi.mock("../utils/logger.js", () => ({
sshLogger: {
+4 -3
View File
@@ -2,10 +2,11 @@ import { type Client, type ClientChannel } from "ssh2";
import { WebSocket } from "ws";
import fs from "fs";
import path from "path";
import { eq } from "drizzle-orm";
import { sshLogger } from "../utils/logger.js";
import { getCurrentSettingValue } from "../database/repositories/current-settings-repository.js";
import { createCurrentSessionRecordingRepository } from "../database/repositories/current-session-recording-repository.js";
import {
getCurrentSettingValue,
createCurrentSessionRecordingRepository,
} from "../database/repositories/factory.js";
const MAX_BUFFER_BYTES = 512 * 1024;
const DATA_DIR = process.env.DATA_DIR ?? "./db/data";
+1 -1
View File
@@ -7,7 +7,7 @@ import ssh2Pkg, {
const { Client, utils: ssh2Utils } = ssh2Pkg;
import { buildSSHAlgorithms } from "../utils/ssh-algorithms.js";
import axios from "axios";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
import { sshLogger, authLogger } from "../utils/logger.js";
import { logAudit } from "../utils/audit-logger.js";
import { AuthManager } from "../utils/auth-manager.js";
+4 -2
View File
@@ -4,8 +4,10 @@ import { Client, type ConnectConfig } from "ssh2";
import { createCorsMiddleware } from "../utils/cors-config.js";
import { AuthManager } from "../utils/auth-manager.js";
import { DataCrypto } from "../utils/data-crypto.js";
import { createCurrentTmuxSessionTagRepository } from "../database/repositories/current-tmux-session-tag-repository.js";
import { createCurrentUserRepository } from "../database/repositories/current-user-repository.js";
import {
createCurrentTmuxSessionTagRepository,
createCurrentUserRepository,
} from "../database/repositories/factory.js";
import { logAudit, getRequestMeta } from "../utils/audit-logger.js";
import { sshLogger } from "../utils/logger.js";
import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js";
+1 -1
View File
@@ -12,7 +12,7 @@ import { WebSocketServer } from "ws";
import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js";
import { ChildProcess } from "child_process";
import axios from "axios";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js";
import type {
SSHHost,
TunnelConfig,
+4 -2
View File
@@ -11,8 +11,10 @@
// ephemeral key, cache the cert, and notify the browser to reconnect.
import { WebSocket } from "ws";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import { createCurrentVaultProfileRepository } from "../database/repositories/current-vault-profile-repository.js";
import {
createCurrentHostResolutionRepository,
createCurrentVaultProfileRepository,
} from "../database/repositories/factory.js";
import { sshLogger } from "../utils/logger.js";
import {
type VaultProfileConfig,
+1 -1
View File
@@ -16,7 +16,7 @@
// The pure (DB-free) signing/OIDC/cert logic lives in vault-signer-core.ts and
// is re-exported here so callers have a single import surface.
import { createCurrentVaultTokenRepository } from "../database/repositories/current-vault-token-repository.js";
import { createCurrentVaultTokenRepository } from "../database/repositories/factory.js";
import { UserCrypto } from "../utils/user-crypto.js";
import { FieldCrypto } from "../utils/field-crypto.js";
import { parseCertValidBefore } from "./vault-signer-core.js";