export interface Reference { sourceCollectionName: string; sourceField: string; targetField: string; targetCollectionName: string; onDelete: string; } class ReferencesMap { protected map: Map = new Map(); addReference(reference: Reference) { if (!reference.onDelete) { reference.onDelete = 'SET NULL'; } reference.onDelete = reference.onDelete.toUpperCase(); const existReference = this.existReference(reference); if (existReference && existReference.onDelete !== reference.onDelete) { if (reference.onDelete === 'SET NULL') { // using existing reference return; } else if (existReference.onDelete === 'SET NULL') { existReference.onDelete = reference.onDelete; } else { throw new Error( `On Delete Conflict, exist reference ${JSON.stringify(existReference)}, new reference ${JSON.stringify( reference, )}`, ); } } if (!existReference) { this.map.set(reference.targetCollectionName, [ ...(this.map.get(reference.targetCollectionName) || []), reference, ]); } } getReferences(collectionName) { return this.map.get(collectionName); } existReference(reference: Reference) { const references = this.map.get(reference.targetCollectionName); if (!references) { return null; } const keys = Object.keys(reference).filter((k) => k !== 'onDelete'); return references.find((ref) => keys.every((key) => ref[key] === reference[key])); } removeReference(reference: Reference) { const references = this.map.get(reference.targetCollectionName); if (!references) { return; } const keys = ['sourceCollectionName', 'sourceField', 'targetField', 'targetCollectionName']; this.map.set( reference.targetCollectionName, references.filter((ref) => !keys.every((key) => ref[key] === reference[key])), ); } } export default ReferencesMap;