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
@@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
const createMock = vi.fn().mockResolvedValue(undefined);
vi.mock("../database/repositories/current-audit-log-repository.js", () => ({
vi.mock("../database/repositories/factory.js", () => ({
createCurrentAuditLogRepository: vi.fn(() => ({
create: createMock,
})),
+1 -1
View File
@@ -1,5 +1,5 @@
import type { Request } from "express";
import { createCurrentAuditLogRepository } from "../database/repositories/current-audit-log-repository.js";
import { createCurrentAuditLogRepository } from "../database/repositories/factory.js";
export interface AuditLogParams {
userId: string;
+7 -5
View File
@@ -12,11 +12,13 @@ import { and, eq, inArray } from "drizzle-orm";
import type { DeviceType } from "./user-agent-parser.js";
import { getDb } from "../database/db/index.js";
import { sessions } from "../database/db/schema.js";
import { createCurrentSettingsRepository } from "../database/repositories/current-settings-repository.js";
import { createCurrentSessionRepository } from "../database/repositories/current-session-repository.js";
import { createCurrentUserRepository } from "../database/repositories/current-user-repository.js";
import { createCurrentApiKeyRepository } from "../database/repositories/current-api-key-repository.js";
import { createCurrentTrustedDeviceRepository } from "../database/repositories/current-trusted-device-repository.js";
import {
createCurrentSettingsRepository,
createCurrentSessionRepository,
createCurrentUserRepository,
createCurrentApiKeyRepository,
createCurrentTrustedDeviceRepository,
} from "../database/repositories/factory.js";
interface AuthenticationResult {
success: boolean;
@@ -13,19 +13,13 @@ const sharedCredentialRepository = {
markNeedsReEncryptionByOriginalCredentialId: vi.fn(),
};
vi.mock("../database/repositories/current-credential-repository.js", () => ({
vi.mock("../database/repositories/factory.js", () => ({
createCurrentCredentialRepository: vi.fn(() => credentialRepository),
createCurrentSharedCredentialRepository: vi.fn(
() => sharedCredentialRepository,
),
}));
vi.mock(
"../database/repositories/current-shared-credential-repository.js",
() => ({
createCurrentSharedCredentialRepository: vi.fn(
() => sharedCredentialRepository,
),
}),
);
describe("CredentialSystemEncryptionMigration", () => {
beforeEach(() => {
vi.restoreAllMocks();
@@ -1,5 +1,7 @@
import { createCurrentCredentialRepository } from "../database/repositories/current-credential-repository.js";
import { createCurrentSharedCredentialRepository } from "../database/repositories/current-shared-credential-repository.js";
import {
createCurrentCredentialRepository,
createCurrentSharedCredentialRepository,
} from "../database/repositories/factory.js";
import { DataCrypto } from "./data-crypto.js";
import { SystemCrypto } from "./system-crypto.js";
import { FieldCrypto } from "./field-crypto.js";
@@ -37,9 +37,7 @@ describe("ensureDatabaseLayerPreupgradeBackup", () => {
dataDir,
version: "2.5.0-test",
now: new Date("2026-06-27T12:00:00.000Z"),
env: {
DATABASE_LAYER_REPOSITORY_ROLLOUT: "settings,users",
} as NodeJS.ProcessEnv,
env: {} as NodeJS.ProcessEnv,
});
expect(result.status).toBe("created");
@@ -67,9 +65,8 @@ describe("ensureDatabaseLayerPreupgradeBackup", () => {
const manifest = JSON.parse(
fs.readFileSync(path.join(result.backupDir!, "manifest.json"), "utf8"),
) as { sourceVersion: string; rollout: { mode: string } };
) as { sourceVersion: string };
expect(manifest.sourceVersion).toBe("2.5.0-test");
expect(manifest.rollout.mode).toBe("partial");
});
it("skips when the marker already exists", () => {
@@ -1,7 +1,6 @@
import fs from "fs";
import path from "path";
import { databaseLogger } from "./logger.js";
import { getRepositoryRolloutStatus } from "../database/repositories/repository-rollout.js";
export const DATABASE_LAYER_PREUPGRADE_BACKUP_MARKER =
".database-layer-preupgrade-backup.json";
@@ -31,7 +30,6 @@ export interface PreupgradeBackupManifest {
sourceVersion: string;
dataDir: string;
backupDir: string;
rollout: ReturnType<typeof getRepositoryRolloutStatus>;
files: BackupFileEntry[];
}
@@ -159,7 +157,6 @@ export function ensureDatabaseLayerPreupgradeBackup(
sourceVersion: options.version ?? env.VERSION ?? "unknown",
dataDir,
backupDir,
rollout: getRepositoryRolloutStatus(env),
files,
};
+6 -4
View File
@@ -1,8 +1,10 @@
import type { Request, Response, NextFunction } from "express";
import { createCurrentRbacAccessRepository } from "../database/repositories/current-rbac-access-repository.js";
import { createCurrentRoleRepository } from "../database/repositories/current-role-repository.js";
import { createCurrentUserRepository } from "../database/repositories/current-user-repository.js";
import { createCurrentHostResolutionRepository } from "../database/repositories/current-host-resolution-repository.js";
import {
createCurrentRbacAccessRepository,
createCurrentRoleRepository,
createCurrentUserRepository,
createCurrentHostResolutionRepository,
} from "../database/repositories/factory.js";
import { databaseLogger } from "./logger.js";
interface AuthenticatedRequest extends Request {
@@ -1,7 +1,9 @@
import { createCurrentCredentialRepository } from "../database/repositories/current-credential-repository.js";
import { createCurrentRbacAccessRepository } from "../database/repositories/current-rbac-access-repository.js";
import { createCurrentRoleRepository } from "../database/repositories/current-role-repository.js";
import { createCurrentSharedCredentialRepository } from "../database/repositories/current-shared-credential-repository.js";
import {
createCurrentCredentialRepository,
createCurrentRbacAccessRepository,
createCurrentRoleRepository,
createCurrentSharedCredentialRepository,
} from "../database/repositories/factory.js";
import type { SharedCredentialRecord } from "../database/repositories/shared-credential-repository.js";
import { DataCrypto } from "./data-crypto.js";
import { FieldCrypto } from "./field-crypto.js";
+1 -1
View File
@@ -1,6 +1,6 @@
import crypto from "crypto";
import { databaseLogger } from "./logger.js";
import { createCurrentSettingsRepository } from "../database/repositories/current-settings-repository.js";
import { createCurrentSettingsRepository } from "../database/repositories/factory.js";
import { SystemCrypto } from "./system-crypto.js";
interface KEKSalt {
+7 -5
View File
@@ -1,8 +1,10 @@
import { createCurrentDismissedAlertRepository } from "../database/repositories/current-dismissed-alert-repository.js";
import { createCurrentFileManagerBookmarkRepository } from "../database/repositories/current-file-manager-bookmark-repository.js";
import { createCurrentTransferRecentRepository } from "../database/repositories/current-transfer-recent-repository.js";
import { createCurrentUserDataExportRepository } from "../database/repositories/current-user-data-export-repository.js";
import { createCurrentUserRepository } from "../database/repositories/current-user-repository.js";
import {
createCurrentDismissedAlertRepository,
createCurrentFileManagerBookmarkRepository,
createCurrentTransferRecentRepository,
createCurrentUserDataExportRepository,
createCurrentUserRepository,
} from "../database/repositories/factory.js";
import { DataCrypto } from "./data-crypto.js";
import { databaseLogger } from "./logger.js";
@@ -1,4 +1,4 @@
import { getCurrentRepositorySqlite } from "../database/repositories/current-repository-runtime.js";
import { getCurrentRepositorySqlite } from "../database/repositories/factory.js";
export interface UserEncryptionMigrationRecord {
id: number | string;