import { assertCircuitInsertProjectCommand, circuitInsertCommandType, circuitStructureCommandSchemaVersion, type CircuitSnapshot, } from "./circuit-structure-project-command.model.js"; import { assertDistributionBoardUpdateProjectCommand, type DistributionBoardUpdateProjectCommand, } from "./distribution-board-project-command.model.js"; import type { SerializedProjectCommand } from "./project-command.model.js"; export const distributionBoardCreateFeederCircuitCommandType = "distribution-board.create-feeder-circuit" as const; export const distributionBoardRemoveFeederCircuitCommandType = "distribution-board.remove-feeder-circuit" as const; export const distributionBoardFeederCircuitCommandSchemaVersion = 1 as const; export interface DistributionBoardFeederCircuitCommandPayload { circuit: CircuitSnapshot; boardUpdate: DistributionBoardUpdateProjectCommand; } export interface DistributionBoardCreateFeederCircuitProjectCommand extends SerializedProjectCommand { schemaVersion: typeof distributionBoardFeederCircuitCommandSchemaVersion; type: typeof distributionBoardCreateFeederCircuitCommandType; } export interface DistributionBoardRemoveFeederCircuitProjectCommand extends SerializedProjectCommand { schemaVersion: typeof distributionBoardFeederCircuitCommandSchemaVersion; type: typeof distributionBoardRemoveFeederCircuitCommandType; } export type DistributionBoardFeederCircuitProjectCommand = | DistributionBoardCreateFeederCircuitProjectCommand | DistributionBoardRemoveFeederCircuitProjectCommand; export function createDistributionBoardCreateFeederCircuitProjectCommand( circuit: CircuitSnapshot, boardUpdate: DistributionBoardUpdateProjectCommand ): DistributionBoardCreateFeederCircuitProjectCommand { const command: DistributionBoardCreateFeederCircuitProjectCommand = { schemaVersion: distributionBoardFeederCircuitCommandSchemaVersion, type: distributionBoardCreateFeederCircuitCommandType, payload: { circuit, boardUpdate }, }; assertDistributionBoardFeederCircuitProjectCommand(command); return command; } export function createDistributionBoardRemoveFeederCircuitProjectCommand( circuit: CircuitSnapshot, boardUpdate: DistributionBoardUpdateProjectCommand ): DistributionBoardRemoveFeederCircuitProjectCommand { const command: DistributionBoardRemoveFeederCircuitProjectCommand = { schemaVersion: distributionBoardFeederCircuitCommandSchemaVersion, type: distributionBoardRemoveFeederCircuitCommandType, payload: { circuit, boardUpdate }, }; assertDistributionBoardFeederCircuitProjectCommand(command); return command; } export function assertDistributionBoardFeederCircuitProjectCommand( command: SerializedProjectCommand ): asserts command is DistributionBoardFeederCircuitProjectCommand { if ( command.schemaVersion !== distributionBoardFeederCircuitCommandSchemaVersion || (command.type !== distributionBoardCreateFeederCircuitCommandType && command.type !== distributionBoardRemoveFeederCircuitCommandType) || !isPlainObject(command.payload) ) { throw new Error("Unsupported distribution-board feeder-circuit command."); } const { circuit, boardUpdate } = command.payload; if (!isPlainObject(boardUpdate)) { throw new Error("Feeder-circuit command requires a board update."); } assertCircuitInsertProjectCommand({ schemaVersion: circuitStructureCommandSchemaVersion, type: circuitInsertCommandType, payload: { circuit }, }); const boardUpdateCommand = boardUpdate as unknown as SerializedProjectCommand; assertDistributionBoardUpdateProjectCommand(boardUpdateCommand); const typedCircuit = circuit as CircuitSnapshot; const typedBoardUpdate: DistributionBoardUpdateProjectCommand = boardUpdateCommand; if (typedCircuit.deviceRows.length !== 0 || !typedCircuit.isReserve) { throw new Error( "A generated feeder circuit must be empty before the board load is linked." ); } const feedingBoard = getChangeValue( typedBoardUpdate, "feedingDistributionBoardId" ); const feedingCircuit = getChangeValue( typedBoardUpdate, "feedingCircuitId" ); if (feedingBoard === undefined || feedingCircuit === undefined) { throw new Error( "Feeder-circuit commands must update both logical feeding references." ); } if ( command.type === distributionBoardCreateFeederCircuitCommandType && (typeof feedingBoard !== "string" || feedingCircuit !== typedCircuit.id) ) { throw new Error( "The created feeder circuit must be linked by the distribution-board update." ); } } function getChangeValue( command: DistributionBoardUpdateProjectCommand, field: "feedingDistributionBoardId" | "feedingCircuitId" ) { return command.payload.changes.find((change) => change.field === field)?.value; } function isPlainObject(value: unknown): value is Record { return value !== null && typeof value === "object" && !Array.isArray(value); }