97 lines
3.0 KiB
TypeScript
97 lines
3.0 KiB
TypeScript
import type { SerializedProjectCommand } from "../../domain/models/project-command.model.js";
|
|
import type {
|
|
AppendedProjectRevision,
|
|
ProjectRevisionSource,
|
|
} from "../../domain/ports/project-revision.store.js";
|
|
import type { AppDatabase } from "../database-context.js";
|
|
import { applyProjectHistoryTransition } from "./project-history.persistence.js";
|
|
import { appendProjectRevision } from "./project-revision.persistence.js";
|
|
|
|
export interface ProjectCommandTransactionInput<
|
|
Command extends SerializedProjectCommand<unknown>,
|
|
> {
|
|
projectId: string;
|
|
expectedRevision: number;
|
|
source: ProjectRevisionSource;
|
|
description?: string;
|
|
actorId?: string;
|
|
historyTargetChangeSetId?: string;
|
|
command: Command;
|
|
}
|
|
|
|
export interface AppliedProjectCommand<
|
|
Forward extends SerializedProjectCommand<unknown>,
|
|
Inverse extends SerializedProjectCommand<unknown>,
|
|
> {
|
|
forward: Forward;
|
|
inverse: Inverse;
|
|
}
|
|
|
|
export function executeProjectCommandTransaction<
|
|
Command extends SerializedProjectCommand<unknown>,
|
|
Inverse extends SerializedProjectCommand<unknown>,
|
|
>(
|
|
database: AppDatabase,
|
|
input: ProjectCommandTransactionInput<Command>,
|
|
applyCommand: (transaction: AppDatabase) => Inverse
|
|
): { revision: AppendedProjectRevision; inverse: Inverse } {
|
|
return executeAppliedProjectCommandTransaction(
|
|
database,
|
|
input,
|
|
(transaction) => ({
|
|
forward: input.command,
|
|
inverse: applyCommand(transaction),
|
|
})
|
|
);
|
|
}
|
|
|
|
export function executeProjectCommandTransactionWithAppliedForward<
|
|
Command extends SerializedProjectCommand<unknown>,
|
|
Forward extends SerializedProjectCommand<unknown>,
|
|
Inverse extends SerializedProjectCommand<unknown>,
|
|
>(
|
|
database: AppDatabase,
|
|
input: ProjectCommandTransactionInput<Command>,
|
|
applyCommand: (
|
|
transaction: AppDatabase
|
|
) => AppliedProjectCommand<Forward, Inverse>
|
|
): { revision: AppendedProjectRevision; inverse: Inverse } {
|
|
return executeAppliedProjectCommandTransaction(
|
|
database,
|
|
input,
|
|
applyCommand
|
|
);
|
|
}
|
|
|
|
function executeAppliedProjectCommandTransaction<
|
|
Command extends SerializedProjectCommand<unknown>,
|
|
Forward extends SerializedProjectCommand<unknown>,
|
|
Inverse extends SerializedProjectCommand<unknown>,
|
|
>(
|
|
database: AppDatabase,
|
|
input: ProjectCommandTransactionInput<Command>,
|
|
applyCommand: (
|
|
transaction: AppDatabase
|
|
) => AppliedProjectCommand<Forward, Inverse>
|
|
): { revision: AppendedProjectRevision; inverse: Inverse } {
|
|
return database.transaction((tx) => {
|
|
const { forward, inverse } = applyCommand(tx);
|
|
const revision = appendProjectRevision(tx, {
|
|
projectId: input.projectId,
|
|
expectedRevision: input.expectedRevision,
|
|
source: input.source,
|
|
description: input.description,
|
|
actorId: input.actorId,
|
|
forward,
|
|
inverse,
|
|
});
|
|
applyProjectHistoryTransition(tx, {
|
|
projectId: input.projectId,
|
|
source: input.source,
|
|
recordedChangeSetId: revision.changeSetId,
|
|
targetChangeSetId: input.historyTargetChangeSetId,
|
|
});
|
|
return { revision, inverse };
|
|
});
|
|
}
|