Remove unused revision repository

This commit is contained in:
2026-07-26 11:40:04 +02:00
parent 4789e01aac
commit 0cedeaa959
7 changed files with 57 additions and 82 deletions
+2
View File
@@ -26,6 +26,8 @@ It must support circuits, device rows, project devices, drag-and-drop restructur
`src/db/repositories/project-command-transaction.persistence.ts` for the
atomic domain-write, revision and history transition boundary. Its applied
forward-command variant preserves derived CircuitDeviceRow override metadata.
- Low-level `appendProjectRevision` persistence is adapter-internal and tested
directly; do not reintroduce a standalone runtime revision repository.
- General Circuit, CircuitDeviceRow, CircuitList and DistributionBoard
repositories expose only active reads. Runtime writes belong in typed command
repositories; direct integration fixtures belong under `tests/support`.
+3
View File
@@ -93,6 +93,9 @@ aus. Für CircuitDeviceRow-Feldänderungen übernimmt eine typisierte Variante d
während der Fachänderung um Override-Metadaten ergänzten Forward-Command. Die
fachlichen Validierungs-, Forward- und Inversenregeln bleiben im jeweiligen
Store.
Die Low-Level-Funktion `appendProjectRevision` bleibt ein internes Detail dieser
Persistenzgrenze und wird direkt mit einer realen SQLite-Transaktion getestet.
Ein eigenständiges Runtime-Revisions-Repository existiert nicht.
`circuit-device-row.insert` und `circuit-device-row.delete` sind atomare
Strukturkommandos. Beim Löschen wird die vollständige Zeile im inversen
Kommando gesichert, sodass Undo dieselbe UUID und alle Fachwerte wiederherstellt.
@@ -350,6 +350,8 @@ Implemented foundation:
restore, share one tested transaction wrapper for domain mutation, revision
append and history transition; its applied-forward variant retains derived
CircuitDeviceRow override metadata
- low-level revision append persistence is tested directly; the unused
standalone runtime revision repository and store interface are removed
- the legacy consumer UI and application read/write endpoints are removed after verified data cutover
- retained legacy rows are accessible only through explicit database upgrade tooling
- project devices no longer persist duplicate legacy power, phase, cosPhi or remark fields
+2 -2
View File
@@ -14,8 +14,8 @@
"build:api": "tsc -p tsconfig.json",
"build:web": "next build",
"start": "node dist/server/index.js",
"test": "tsx --test tests/project-device-schema.test.ts tests/project-device-schema-migration.test.ts tests/project-device-placement.service.test.ts tests/project-device-sync.service.test.ts tests/legacy-consumer-migration-planner.test.ts tests/legacy-consumer-migration.repository.test.ts tests/circuit-numbering.service.test.ts tests/circuit-power-calculation.test.ts tests/circuit-tree.controller.test.ts tests/circuit-editor-history.test.ts tests/circuit-grid-insertion.test.ts tests/circuit-grid-safety.test.ts tests/circuit-grid-model.test.ts tests/circuit-structure-command.test.ts tests/circuit-device-row-move-command.test.ts tests/circuit-section-reorder-command.test.ts tests/circuit-section-renumber-command.test.ts tests/circuit-grid-projection.test.ts tests/distribution-board-structure-project-command.repository.test.ts tests/project-location-structure-project-command.repository.test.ts tests/project-device-project-command.repository.test.ts tests/project-device-structure-project-command.repository.test.ts tests/project-device-row-sync-project-command.repository.test.ts tests/circuit-section-reorder-project-command.repository.test.ts tests/circuit-section-renumber-project-command.repository.test.ts tests/project-command.model.test.ts tests/project-revision.repository.test.ts tests/circuit-project-command.repository.test.ts tests/circuit-structure-project-command.repository.test.ts tests/circuit-device-row-project-command.repository.test.ts tests/circuit-device-row-structure-project-command.repository.test.ts tests/circuit-device-row-move-project-command.repository.test.ts tests/project-history.repository.test.ts tests/project-history-timeline.test.ts tests/project-version-history.test.ts tests/project-settings-project-command.repository.test.ts tests/project-state-snapshot.test.ts tests/project-snapshot-policy.test.ts tests/project-snapshot.repository.test.ts tests/project-state-restore-command.repository.test.ts tests/project-command.service.test.ts tests/database-backup.test.ts",
"test:watch": "tsx --watch --test tests/project-device-schema.test.ts tests/project-device-schema-migration.test.ts tests/project-device-placement.service.test.ts tests/project-device-sync.service.test.ts tests/legacy-consumer-migration-planner.test.ts tests/legacy-consumer-migration.repository.test.ts tests/circuit-numbering.service.test.ts tests/circuit-power-calculation.test.ts tests/circuit-tree.controller.test.ts tests/circuit-editor-history.test.ts tests/circuit-grid-insertion.test.ts tests/circuit-grid-safety.test.ts tests/circuit-grid-model.test.ts tests/circuit-structure-command.test.ts tests/circuit-device-row-move-command.test.ts tests/circuit-section-reorder-command.test.ts tests/circuit-section-renumber-command.test.ts tests/circuit-grid-projection.test.ts tests/distribution-board-structure-project-command.repository.test.ts tests/project-location-structure-project-command.repository.test.ts tests/project-device-project-command.repository.test.ts tests/project-device-structure-project-command.repository.test.ts tests/project-device-row-sync-project-command.repository.test.ts tests/circuit-section-reorder-project-command.repository.test.ts tests/circuit-section-renumber-project-command.repository.test.ts tests/project-command.model.test.ts tests/project-revision.repository.test.ts tests/circuit-project-command.repository.test.ts tests/circuit-structure-project-command.repository.test.ts tests/circuit-device-row-project-command.repository.test.ts tests/circuit-device-row-structure-project-command.repository.test.ts tests/circuit-device-row-move-project-command.repository.test.ts tests/project-history.repository.test.ts tests/project-history-timeline.test.ts tests/project-version-history.test.ts tests/project-settings-project-command.repository.test.ts tests/project-state-snapshot.test.ts tests/project-snapshot-policy.test.ts tests/project-snapshot.repository.test.ts tests/project-state-restore-command.repository.test.ts tests/project-command.service.test.ts tests/database-backup.test.ts",
"test": "tsx --test tests/project-device-schema.test.ts tests/project-device-schema-migration.test.ts tests/project-device-placement.service.test.ts tests/project-device-sync.service.test.ts tests/legacy-consumer-migration-planner.test.ts tests/legacy-consumer-migration.repository.test.ts tests/circuit-numbering.service.test.ts tests/circuit-power-calculation.test.ts tests/circuit-tree.controller.test.ts tests/circuit-editor-history.test.ts tests/circuit-grid-insertion.test.ts tests/circuit-grid-safety.test.ts tests/circuit-grid-model.test.ts tests/circuit-structure-command.test.ts tests/circuit-device-row-move-command.test.ts tests/circuit-section-reorder-command.test.ts tests/circuit-section-renumber-command.test.ts tests/circuit-grid-projection.test.ts tests/distribution-board-structure-project-command.repository.test.ts tests/project-location-structure-project-command.repository.test.ts tests/project-device-project-command.repository.test.ts tests/project-device-structure-project-command.repository.test.ts tests/project-device-row-sync-project-command.repository.test.ts tests/circuit-section-reorder-project-command.repository.test.ts tests/circuit-section-renumber-project-command.repository.test.ts tests/project-command.model.test.ts tests/project-revision.persistence.test.ts tests/circuit-project-command.repository.test.ts tests/circuit-structure-project-command.repository.test.ts tests/circuit-device-row-project-command.repository.test.ts tests/circuit-device-row-structure-project-command.repository.test.ts tests/circuit-device-row-move-project-command.repository.test.ts tests/project-history.repository.test.ts tests/project-history-timeline.test.ts tests/project-version-history.test.ts tests/project-settings-project-command.repository.test.ts tests/project-state-snapshot.test.ts tests/project-snapshot-policy.test.ts tests/project-snapshot.repository.test.ts tests/project-state-restore-command.repository.test.ts tests/project-command.service.test.ts tests/database-backup.test.ts",
"test:watch": "tsx --watch --test tests/project-device-schema.test.ts tests/project-device-schema-migration.test.ts tests/project-device-placement.service.test.ts tests/project-device-sync.service.test.ts tests/legacy-consumer-migration-planner.test.ts tests/legacy-consumer-migration.repository.test.ts tests/circuit-numbering.service.test.ts tests/circuit-power-calculation.test.ts tests/circuit-tree.controller.test.ts tests/circuit-editor-history.test.ts tests/circuit-grid-insertion.test.ts tests/circuit-grid-safety.test.ts tests/circuit-grid-model.test.ts tests/circuit-structure-command.test.ts tests/circuit-device-row-move-command.test.ts tests/circuit-section-reorder-command.test.ts tests/circuit-section-renumber-command.test.ts tests/circuit-grid-projection.test.ts tests/distribution-board-structure-project-command.repository.test.ts tests/project-location-structure-project-command.repository.test.ts tests/project-device-project-command.repository.test.ts tests/project-device-structure-project-command.repository.test.ts tests/project-device-row-sync-project-command.repository.test.ts tests/circuit-section-reorder-project-command.repository.test.ts tests/circuit-section-renumber-project-command.repository.test.ts tests/project-command.model.test.ts tests/project-revision.persistence.test.ts tests/circuit-project-command.repository.test.ts tests/circuit-structure-project-command.repository.test.ts tests/circuit-device-row-project-command.repository.test.ts tests/circuit-device-row-structure-project-command.repository.test.ts tests/circuit-device-row-move-project-command.repository.test.ts tests/project-history.repository.test.ts tests/project-history-timeline.test.ts tests/project-version-history.test.ts tests/project-settings-project-command.repository.test.ts tests/project-state-snapshot.test.ts tests/project-snapshot-policy.test.ts tests/project-snapshot.repository.test.ts tests/project-state-restore-command.repository.test.ts tests/project-command.service.test.ts tests/database-backup.test.ts",
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:backup": "tsx scripts/db-backup.ts",
@@ -1,31 +0,0 @@
import { eq } from "drizzle-orm";
import { ProjectRevisionConflictError } from "../../domain/errors/project-revision-conflict.error.js";
import type {
AppendProjectRevisionInput,
AppendedProjectRevision,
ProjectRevisionStore,
} from "../../domain/ports/project-revision.store.js";
import type { AppDatabase } from "../database-context.js";
import { projects } from "../schema/projects.js";
import { appendProjectRevision } from "./project-revision.persistence.js";
export { ProjectRevisionConflictError };
export class ProjectRevisionRepository implements ProjectRevisionStore {
constructor(private readonly database: AppDatabase) {}
getCurrentRevision(projectId: string) {
const project = this.database
.select({ currentRevision: projects.currentRevision })
.from(projects)
.where(eq(projects.id, projectId))
.get();
return project?.currentRevision ?? null;
}
append(input: AppendProjectRevisionInput): AppendedProjectRevision {
return this.database.transaction((tx) =>
appendProjectRevision(tx, input)
);
}
}
@@ -24,8 +24,3 @@ export interface AppendedProjectRevision {
revisionNumber: number;
createdAtIso: string;
}
export interface ProjectRevisionStore {
getCurrentRevision(projectId: string): number | null;
append(input: AppendProjectRevisionInput): AppendedProjectRevision;
}
@@ -5,12 +5,11 @@ import { eq } from "drizzle-orm";
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
import {
createDatabaseContext,
type AppDatabase,
type DatabaseContext,
} from "../src/db/database-context.js";
import {
ProjectRevisionConflictError,
ProjectRevisionRepository,
} from "../src/db/repositories/project-revision.repository.js";
import { ProjectRevisionConflictError } from "../src/domain/errors/project-revision-conflict.error.js";
import { appendProjectRevision } from "../src/db/repositories/project-revision.persistence.js";
import { ProjectSnapshotRepository } from "../src/db/repositories/project-snapshot.repository.js";
import { projectChangeSets } from "../src/db/schema/project-change-sets.js";
import { projectRevisions } from "../src/db/schema/project-revisions.js";
@@ -27,40 +26,50 @@ function createTestDatabase(): DatabaseContext {
}
function appendTestRevision(
repository: ProjectRevisionRepository,
database: AppDatabase,
expectedRevision: number
) {
return repository.append({
projectId: "project-1",
expectedRevision,
source: "user",
description: "Stromkreis bearbeiten",
actorId: "test-user",
forward: {
schemaVersion: 1,
type: "circuit.update",
payload: { circuitId: "circuit-1", displayName: "Neu" },
},
inverse: {
schemaVersion: 1,
type: "circuit.update",
payload: { circuitId: "circuit-1", displayName: "Alt" },
},
});
return database.transaction((tx) =>
appendProjectRevision(tx, {
projectId: "project-1",
expectedRevision,
source: "user",
description: "Stromkreis bearbeiten",
actorId: "test-user",
forward: {
schemaVersion: 1,
type: "circuit.update",
payload: { circuitId: "circuit-1", displayName: "Neu" },
},
inverse: {
schemaVersion: 1,
type: "circuit.update",
payload: { circuitId: "circuit-1", displayName: "Alt" },
},
})
);
}
describe("project revision repository", () => {
function getCurrentRevision(database: AppDatabase, projectId: string) {
return (
database
.select({ currentRevision: projects.currentRevision })
.from(projects)
.where(eq(projects.id, projectId))
.get()?.currentRevision ?? null
);
}
describe("project revision persistence", () => {
it("appends immutable revision metadata and payloads with a monotonic number", () => {
const context = createTestDatabase();
try {
const repository = new ProjectRevisionRepository(context.db);
assert.equal(repository.getCurrentRevision("project-1"), 0);
const appended = appendTestRevision(repository, 0);
assert.equal(getCurrentRevision(context.db, "project-1"), 0);
const appended = appendTestRevision(context.db, 0);
assert.equal(appended.projectId, "project-1");
assert.equal(appended.revisionNumber, 1);
assert.equal(repository.getCurrentRevision("project-1"), 1);
assert.equal(getCurrentRevision(context.db, "project-1"), 1);
const revision = context.db
.select()
@@ -105,9 +114,9 @@ describe("project revision repository", () => {
}),
});
const next = appendTestRevision(repository, 1);
const next = appendTestRevision(context.db, 1);
assert.equal(next.revisionNumber, 2);
assert.equal(repository.getCurrentRevision("project-1"), 2);
assert.equal(getCurrentRevision(context.db, "project-1"), 2);
} finally {
context.close();
}
@@ -116,18 +125,17 @@ describe("project revision repository", () => {
it("rejects a stale expected revision without writing history", () => {
const context = createTestDatabase();
try {
const repository = new ProjectRevisionRepository(context.db);
appendTestRevision(repository, 0);
appendTestRevision(context.db, 0);
assert.throws(
() => appendTestRevision(repository, 0),
() => appendTestRevision(context.db, 0),
(error) =>
error instanceof ProjectRevisionConflictError &&
error.expectedRevision === 0 &&
error.actualRevision === 1
);
assert.equal(repository.getCurrentRevision("project-1"), 1);
assert.equal(getCurrentRevision(context.db, "project-1"), 1);
assert.equal(context.db.select().from(projectRevisions).all().length, 1);
assert.equal(context.db.select().from(projectChangeSets).all().length, 1);
} finally {
@@ -145,14 +153,12 @@ describe("project revision repository", () => {
SELECT RAISE(ABORT, 'forced change-set failure');
END;
`);
const repository = new ProjectRevisionRepository(context.db);
assert.throws(
() => appendTestRevision(repository, 0),
() => appendTestRevision(context.db, 0),
/forced change-set failure/
);
assert.equal(repository.getCurrentRevision("project-1"), 0);
assert.equal(getCurrentRevision(context.db, "project-1"), 0);
assert.equal(context.db.select().from(projectRevisions).all().length, 0);
assert.equal(context.db.select().from(projectChangeSets).all().length, 0);
} finally {
@@ -163,7 +169,6 @@ describe("project revision repository", () => {
it("captures and retains automatic snapshots without deleting named snapshots", () => {
const context = createTestDatabase();
try {
const revisions = new ProjectRevisionRepository(context.db);
const snapshots = new ProjectSnapshotRepository(context.db);
const named = snapshots.createNamed({
projectId: "project-1",
@@ -177,7 +182,7 @@ describe("project revision repository", () => {
expectedRevision < 325;
expectedRevision += 1
) {
appendTestRevision(revisions, expectedRevision);
appendTestRevision(context.db, expectedRevision);
}
const stored = context.db
@@ -234,13 +239,12 @@ describe("project revision repository", () => {
it("rolls back revision 25 when automatic snapshot persistence fails", () => {
const context = createTestDatabase();
try {
const repository = new ProjectRevisionRepository(context.db);
for (
let expectedRevision = 0;
expectedRevision < 24;
expectedRevision += 1
) {
appendTestRevision(repository, expectedRevision);
appendTestRevision(context.db, expectedRevision);
}
context.sqlite.exec(`
CREATE TRIGGER fail_automatic_project_snapshot
@@ -252,10 +256,10 @@ describe("project revision repository", () => {
`);
assert.throws(
() => appendTestRevision(repository, 24),
() => appendTestRevision(context.db, 24),
/forced automatic snapshot failure/
);
assert.equal(repository.getCurrentRevision("project-1"), 24);
assert.equal(getCurrentRevision(context.db, "project-1"), 24);
assert.equal(
context.db.select().from(projectRevisions).all().length,
24