import { DocumentData , FieldPath , FirebaseAdmin , Query , QueryDocumentSnapshot , QuerySnapshot , Transaction } from '../../../client/firebase-admin' ; import { RepositoryModel } from '../../../models/index.model' ; import { GitHubRepositoryMapper , GitHubRepositoryModel } from '../repository.mapper' ; import { isExistProperties , Repository , User } from './shared' ; type Action = 'created' | 'deleted' | 'archived' | 'unarchived' | 'edited' | 'renamed' | 'transferred' | 'publicized' | 'privatized' ; export interface RepositoryEventInput { action : Action ; changes ? : { repository : { name : { from : string ; } ; } ; } ; repository : Repository ; sender : User ; } export class RepositoryEventModel implements RepositoryEventInput { action : Action ; changes ? : { repository : { name : { from : string ; } ; } ; } ; repository : Repository ; sender : User ; constructor ( input ) { Object . assign ( this , input ) ; } public static isCurrentModel ( input ) { const requireKeys = [ 'action' , 'repository' , 'sender' ] ; const objKeys = Object . keys ( input ) ; let length = requireKeys . length ; if ( objKeys . find ( ( elem ) => elem === 'changes' ) ) { ++ length ; } return objKeys . length === length && isExistProperties ( input , requireKeys ) ; } public async updateData ( ) { switch ( this . action ) { case 'edited' : { await this . edited ( ) ; break ; } case 'renamed' : { await this . renamed ( ) ; break ; } case 'transferred' : { await this . transferred ( ) ; break ; } case 'publicized' : { await this . publicized ( ) ; break ; } case 'privatized' : { await this . privatized ( ) ; break ; } } } private async edited ( ) { const repository = await RepositoryModel . getRepositoryById ( this . repository . id ) ; const usersRef = FirebaseAdmin . firestore ( ) . collection ( 'users' ) . where ( new FieldPath ( 'repositories' , 'uids' ) , 'array-contains' , repository . uid ) ; const newMinDataRepo = GitHubRepositoryMapper . import ( this . repository ) ; 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 foundIndex = repos . findIndex ( ( item ) => item . uid && item . uid === repository . uid ) ; if ( foundIndex > - 1 ) { Object . assign ( repos [ foundIndex ] , newMinDataRepo ) ; t . update ( element . ref , { repositories : { ... userData . repositories , data : repos } } ) ; } } } ) ; } ) ; } ) ; const newDataRepo = GitHubRepositoryMapper . import ( this . repository , 'all' ) ; Object . assign ( repository , newDataRepo ) ; await RepositoryModel . saveRepository ( repository ) ; } private async renamed ( ) { await this . edited ( ) ; } private async transferred ( ) { await this . edited ( ) ; } private async publicized ( ) { await this . edited ( ) ; } private async privatized ( ) { await this . edited ( ) ; } }