import { firestore , CloudFunction , EventContext } from 'firebase-functions' ; import { Logger } from '../client/logger' ; import { GitHubRepositoryModel } from '../mappers/github/index.mapper' ; import { DocumentData , DocumentReference , DocumentSnapshot , FieldPath , FirebaseAdmin , Query , QueryDocumentSnapshot , QuerySnapshot , Transaction } from './../client/firebase-admin' ; async function addProjects ( repositoryUid , repo ) { const projects = ( await FirebaseAdmin . firestore ( ) . collection ( 'projects' ) . where ( 'repositories' , 'array-contains' , repositoryUid ) . get ( ) ) . docs ; if ( ! Array . isArray ( repo . projects ) ) { repo . projects = [ ] ; } for ( const project of projects ) { repo . projects . push ( project . id ) ; } if ( repo . projects . length > 0 ) { return true ; } return false ; } async function removeDublicateRepository ( repositoryUid , repo , repoRef ) { const repoQuerySnap = ( await FirebaseAdmin . firestore ( ) . collection ( 'repositories' ) . where ( 'id' , '==' , repo . id ) . where ( 'uid' , '<' , repositoryUid ) . where ( 'uid' , '>' , repositoryUid ) . get ( ) ) ; if ( repoQuerySnap . empty ) { return true ; } else { const existRepoUid = repoQuerySnap . docs . shift ( ) . id ; const usersRef = FirebaseAdmin . firestore ( ) . collection ( 'users' ) . where ( new FieldPath ( 'repositories' , 'uids' ) , 'array-contains' , repositoryUid ) ; await FirebaseAdmin . firestore ( ) . runTransaction ( ( t ) => { return t . get ( usersRef ) . then ( ( snap ) => { snap . forEach ( ( element ) => { const userData = element . data ( ) ; if ( userData . repositories && Array . isArray ( userData . repositories . data ) && userData . repositories . data . length > 0 ) { const repos = userData . repositories . data ; const uids = userData . repositories . uids ; const foundIndexObj = repos . findIndex ( ( item ) => item . uid && item . uid === repositoryUid ) ; const foundIndexUids = uids . findIndex ( ( uid ) => uid === repositoryUid ) ; if ( foundIndexObj > - 1 && foundIndexUids > - 1 ) { repos [ foundIndexObj ] . uid = existRepoUid ; uids [ foundIndexUids ] = existRepoUid ; t . update ( element . ref , { repositories : { ... userData . repositories , data : repos , uids } } ) ; } } } ) ; } ) ; } ) ; const projectsRef = FirebaseAdmin . firestore ( ) . collection ( 'projects' ) . where ( 'repositories' , 'array-contains' , repositoryUid ) ; await FirebaseAdmin . firestore ( ) . runTransaction ( ( t ) => { return t . get ( projectsRef ) . then ( ( snap ) => { snap . forEach ( ( element ) => { const projectData = element . data ( ) ; if ( Array . isArray ( projectData . repositories ) && projectData . repositories . length > 0 ) { const uids = projectData . repositories ; const foundIndex = uids . findIndex ( ( uid ) => uid === repositoryUid ) ; if ( foundIndex > - 1 ) { uids [ foundIndex ] = existRepoUid ; t . update ( element . ref , { repositories : uids } ) ; } } } ) ; } ) ; } ) ; await repoRef . delete ( ) ; return false ; } } export const onCreateRepository = firestore . document ( 'repositories/{repositoryUid}' ) . onCreate ( async ( repositorySnapshot , context ) => { try { const newData = repositorySnapshot . data ( ) ; let isNeedUpdate = await removeDublicateRepository ( context . params . repositoryUid , newData , repositorySnapshot . ref ) ; isNeedUpdate = isNeedUpdate && await addProjects ( context . params . repositoryUid , newData ) ; if ( isNeedUpdate ) { await repositorySnapshot . ref . update ( newData ) ; } } catch ( err ) { Logger . error ( err ) ; throw new Error ( err ) ; } } ) ;