import type { Project } from '../model/Project'; import type { Command } from './Command'; /** * Several commands as one undo step. If one throws, the ones already done are rolled back before * re-throwing, so the project is never left half-changed. */ export class CompoundCommand implements Command { constructor( readonly label: string, private readonly commands: readonly Command[], ) {} execute(project: Project): void { const done: Command[] = []; try { for (const command of this.commands) { command.execute(project); done.push(command); } } catch (error) { for (const command of done.reverse()) command.undo(project); throw error; } } undo(project: Project): void { for (let i = this.commands.length - 1; i >= 0; i--) this.commands[i]!.undo(project); } } /** A lone command stays itself, so the undo step keeps its own label. */ export function oneStep(label: string, commands: readonly Command[]): Command { return commands.length === 1 ? commands[0]! : new CompoundCommand(label, commands); }