/** Pure frontend preflight/candidate for an authoritative backend space delete. */ export interface SpaceDeletionDependencyReport { markerIds: string[]; count: number; } const clone = (value: T): T => JSON.parse(JSON.stringify(value)); export function collectSpaceMarkerDependencies( config: any, layout: Record, spaceId: string, ): SpaceDeletionDependencyReport { const space = (config?.spaces || []).find((item: any) => item?.id === spaceId); const roomIds = new Set( (space?.rooms || []).map((room: any) => String(room?.id || '')).filter(Boolean), ); const markerIds = [...new Set((config?.markers || []) .filter((marker: any) => marker?.removed !== true && typeof marker?.id === 'string') .filter((marker: any) => marker.space === spaceId || (typeof marker.room_id === 'string' && roomIds.has(marker.room_id)) || layout?.[marker.id]?.s === spaceId) .map((marker: any) => marker.id))] .sort((a: string, b: string) => a.localeCompare(b)); return { markerIds, count: markerIds.length }; } export function createSpaceDeletionCandidate( configIn: any, layoutIn: Record, spaceId: string, ): { config: any; layout: Record; dependencies: SpaceDeletionDependencyReport } { const dependencies = collectSpaceMarkerDependencies(configIn, layoutIn, spaceId); const config = clone(configIn); const layout = clone(layoutIn || {}); const spaces = config.spaces || []; const deletingLastSpace = spaces.length === 1 && spaces[0]?.id === spaceId; if (dependencies.count && !deletingLastSpace) return { config, layout, dependencies }; const space = (config.spaces || []).find((item: any) => item?.id === spaceId); const roomIds = new Set( (space?.rooms || []).map((room: any) => String(room?.id || '')).filter(Boolean), ); config.spaces = (config.spaces || []).filter((item: any) => item?.id !== spaceId); for (const marker of config.markers || []) { const markerOwnsPosition = typeof marker?.id === 'string' && layout?.[marker.id]?.s === spaceId; const referencesDeletedSpace = marker?.space === spaceId || (typeof marker?.room_id === 'string' && roomIds.has(marker.room_id)) || markerOwnsPosition; if (deletingLastSpace && referencesDeletedSpace) { delete marker.space; delete marker.room_id; continue; } if (marker?.removed !== true) continue; if (marker.space === spaceId) delete marker.space; if (typeof marker.room_id === 'string' && roomIds.has(marker.room_id)) delete marker.room_id; } for (const [key, position] of Object.entries(layout)) { if ((position as any)?.s === spaceId) delete layout[key]; } return { config, layout, dependencies }; }