import YAML from 'yaml'; import _ from 'lodash'; import { extractContainerNamesFromYaml } from '../container-names'; /** * Validates Docker Compose YAML content * @param yaml - The YAML content to validate * @param containerNames - Array of container names currently running in the environment * @param originalContainerNames - Array of original container names from the stack (before edit) * @returns Error message if validation fails, empty string if valid */ export function validateYAML( yaml: string, containerNames: string[] = [], originalContainerNames: string[] = [] ): string { let yamlObject; try { yamlObject = YAML.parse(yaml, { maxAliasCount: 10000 }); } catch (err) { return `There is an error in the yaml syntax: ${err}`; } const names = extractContainerNamesFromYaml(yamlObject); // Find containers that are: // 1. In the current environment (containerNames) // 2. NOT in the original stack (originalContainerNames) // 3. Present in the new YAML (names) // This identifies conflicts with other stacks/containers const duplicateContainers = _.intersection( _.difference(containerNames, originalContainerNames), names ); if (duplicateContainers.length === 0) { return ''; } return `${ duplicateContainers.length === 1 ? 'This container name is' : 'These container names are' } already used by another container running in this environment: ${_.join( duplicateContainers, ', ' )}.`; } /** * Checks if the YAML content has changed (ignoring line ending differences) * @param original - Original YAML content * @param updated - Updated YAML content * @returns True if content has changed, false otherwise */ export function hasYamlChanged(original: string, updated: string): boolean { return normalizeLineEndings(original) !== normalizeLineEndings(updated); function normalizeLineEndings(str: string) { return str.replace(/(\r\n|\n|\r)/gm, ''); } }