import Sequelize , { Op , WhereOptions } from "sequelize" ; import _ from "lodash" ; import RepoSyncState from "./reposyncstate" ; export enum SyncStatus { PENDING = "PENDING" , COMPLETE = "COMPLETE" , ACTIVE = "ACTIVE" , FAILED = "FAILED" } export interface RepoSyncStateObject { installationId ? : number ; jiraHost ? : string ; numberOfSyncedRepos ? : number ; repos ? : Repositories ; } interface SyncStatusCount { syncStatus : string ; count : number ; } export interface Repositories { [ id ] : RepositoryData ; } export interface RepositoryData { repository ? : Repository ; pullStatus ? : TaskStatus ; branchStatus ? : TaskStatus ; commitStatus ? : TaskStatus ; lastBranchCursor ? : string ; lastCommitCursor ? : string ; lastPullCursor ? : number ; [ key ] : unknown ; } export type TaskStatus = "pending" | "complete" | "failed" ; export interface Repository { id : string ; name : string ; full_name : string ; owner : { login : string ; } ; html_url : string ; updated_at : number ; } export default class Subscription extends Sequelize . Model { id : number ; gitHubInstallationId : number ; jiraHost : string ; selectedRepositories ? : number [ ] ; syncStatus ? : SyncStatus ; syncWarning ? : string ; jiraClientKey : string ; updatedAt : Date ; createdAt : Date ; numberOfSyncedRepos ? : number ; static async getAllForHost ( host ) { return Subscription . findAll ( { where : { jiraHost : host } } ) ; } static getAllForInstallation ( installationId ) { return Subscription . findAll ( { where : { gitHubInstallationId : installationId } } ) ; } static getAllFiltered ( installationIds = [ ] , statusTypes = [ "FAILED" , "PENDING" , "ACTIVE" ] , offset = 0 , limit ? , inactiveForSeconds ? ) { const andFilter = [ ] ; if ( statusTypes ?. length > 0 ) { andFilter . push ( { syncStatus : { [ Op . in ] : statusTypes } } ) ; } if ( installationIds ?. length > 0 ) { andFilter . push ( { gitHubInstallationId : { [ Op . in ] : _ . uniq ( installationIds ) } } ) ; } if ( inactiveForSeconds ) { const xSecondsAgo = new Date ( new Date ( ) . getTime ( ) - ( inactiveForSeconds * 1000 ) ) ; andFilter . push ( { updatedAt : { [ Op . lt ] : xSecondsAgo } } ) ; } return Subscription . findAll ( { where : { [ Op . and ] : andFilter } , limit , offset , order : [ [ "updatedAt" , "DESC" ] ] } ) ; } static getAllForClientKey ( clientKey ) { return Subscription . findAll ( { where : { jiraClientKey : clientKey } } ) ; } static getSingleInstallation ( jiraHost , gitHubInstallationId ) { return Subscription . findOne ( { where : { jiraHost , gitHubInstallationId } } ) ; } static async getInstallationForClientKey ( clientKey , installationId ) { return Subscription . findOne ( { where : { jiraClientKey : clientKey , gitHubInstallationId : installationId } } ) ; } static async install ( payload ) { const [ subscription ] = await Subscription . findOrCreate ( { where : { gitHubInstallationId : payload . installationId , jiraHost : payload . host , jiraClientKey : payload . clientKey } } ) ; return subscription ; } static async uninstall ( payload ) { await Subscription . destroy ( { where : { gitHubInstallationId : payload . installationId , jiraHost : payload . host } } ) ; } static async syncStatusCounts ( ) { const [ results ] = await this . sequelize ?. query ( `SELECT "syncStatus", COUNT(*)
			 FROM "Subscriptions"
			 GROUP BY "syncStatus"` ) ; return results as SyncStatusCount [ ] ; } async updateSyncState ( updatedState ) { const state = _ . merge ( await RepoSyncState . toRepoJson ( this ) , updatedState ) ; await RepoSyncState . updateFromRepoJson ( this , state ) ; return this ; } async updateRepoSyncStateItem ( repositoryId , key , value ) { await RepoSyncState . updateRepoForSubscription ( this , Number ( repositoryId ) , key , value ) ; return this ; } async uninstall ( ) { await this . destroy ( ) ; } } export interface SubscriptionPayload { installationId : number ; host : string ; } export interface SubscriptionInstallPayload extends SubscriptionPayload { clientKey : string ; }