Persist circuit reorders

This commit is contained in:
2026-07-25 21:22:10 +02:00
parent 08a2775a88
commit abcb468807
26 changed files with 914 additions and 372 deletions
@@ -0,0 +1,94 @@
import {
assertCircuitSectionReorderProjectCommand,
circuitSectionReorderCommandSchemaVersion,
type CircuitSectionReorderAssignment,
} from "./circuit-section-reorder-project-command.model.js";
import type { SerializedProjectCommand } from "./project-command.model.js";
export const circuitSectionsReorderCommandType =
"circuit.reorder-sections" as const;
export const circuitSectionsReorderCommandSchemaVersion =
circuitSectionReorderCommandSchemaVersion;
export interface CircuitSectionsReorderSection {
sectionId: string;
assignments: CircuitSectionReorderAssignment[];
}
export interface CircuitSectionsReorderCommandPayload {
sections: CircuitSectionsReorderSection[];
}
export interface CircuitSectionsReorderProjectCommand
extends SerializedProjectCommand<CircuitSectionsReorderCommandPayload> {
schemaVersion: typeof circuitSectionsReorderCommandSchemaVersion;
type: typeof circuitSectionsReorderCommandType;
}
export function createCircuitSectionsReorderProjectCommand(
sections: CircuitSectionsReorderSection[]
): CircuitSectionsReorderProjectCommand {
const command: CircuitSectionsReorderProjectCommand = {
schemaVersion: circuitSectionsReorderCommandSchemaVersion,
type: circuitSectionsReorderCommandType,
payload: { sections },
};
assertCircuitSectionsReorderProjectCommand(command);
return command;
}
export function assertCircuitSectionsReorderProjectCommand(
command: SerializedProjectCommand<unknown>
): asserts command is CircuitSectionsReorderProjectCommand {
if (
command.schemaVersion !==
circuitSectionsReorderCommandSchemaVersion ||
command.type !== circuitSectionsReorderCommandType
) {
throw new Error("Unsupported circuit sections reorder command.");
}
if (!isPlainObject(command.payload)) {
throw new Error(
"Circuit sections reorder payload must be an object."
);
}
const sections = command.payload.sections;
if (!Array.isArray(sections) || sections.length === 0) {
throw new Error(
"Circuit sections reorder command requires sections."
);
}
const sectionIds = new Set<string>();
for (const section of sections) {
if (!isPlainObject(section)) {
throw new Error(
"Circuit sections reorder command contains an invalid section."
);
}
if (
typeof section.sectionId !== "string" ||
!section.sectionId.trim()
) {
throw new Error("sectionId must be a non-empty string.");
}
if (sectionIds.has(section.sectionId)) {
throw new Error(
"Circuit sections reorder command contains duplicate section ids."
);
}
assertCircuitSectionReorderProjectCommand({
schemaVersion: circuitSectionReorderCommandSchemaVersion,
type: "circuit.reorder-section",
payload: {
sectionId: section.sectionId,
assignments: section.assignments,
},
});
sectionIds.add(section.sectionId);
}
}
function isPlainObject(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === "object" && !Array.isArray(value);
}