diff --git a/.changeset/pretty-pigs-brush.md b/.changeset/pretty-pigs-brush.md new file mode 100644 index 0000000..b39979d --- /dev/null +++ b/.changeset/pretty-pigs-brush.md @@ -0,0 +1,7 @@ +--- +'gov4git-desktop-app': patch +--- + +Filter out deleted communities + +- Addresses #114, #128 diff --git a/src/electron/services/CommunityService.ts b/src/electron/services/CommunityService.ts index af05510..79c581c 100644 --- a/src/electron/services/CommunityService.ts +++ b/src/electron/services/CommunityService.ts @@ -7,6 +7,7 @@ import { DB } from '../db/db.js' import { communities, type Community, + motions, type Policy, type User, } from '../db/schema.js' @@ -88,6 +89,48 @@ export class CommunityService extends AbstractCommunityService { this.policyService = this.services.load('policy') } + private communityExists = async ( + user: User, + community: Community, + ): Promise => { + const projectRepoSegments = urlToRepoSegments(community.projectUrl) + const projectRepoExists = await this.gitHubService.doesRepoExist({ + repoName: projectRepoSegments.repo, + username: projectRepoSegments.owner, + token: user.pat, + }) + if (!projectRepoExists) return false + const communityRepoSegments = urlToRepoSegments(community.url) + return await this.gitHubService.doesRepoExist({ + repoName: communityRepoSegments.repo, + username: communityRepoSegments.owner, + token: user.pat, + }) + } + + public deleteCommunity = async (url: string) => { + await Promise.all([ + this.db.delete(communities).where(eq(communities.url, url)), + this.db.delete(motions).where(eq(motions.communityUrl, url)), + ]) + } + + private removeNonExistentCommunities = async ( + user: User, + communityList: Community[], + ): Promise => { + const newCommunityList: Community[] = [] + for (const community of communityList) { + const exists = await this.communityExists(user, community) + if (!exists) { + await this.deleteCommunity(community.url) + } else { + newCommunityList.push(community) + } + } + return newCommunityList + } + public getCommunity = async (): Promise => { const user = await this.userService.getUser() if (user == null) return null @@ -99,6 +142,10 @@ export class CommunityService extends AbstractCommunityService { .limit(1) )[0] if (community == null) return null + if (!(await this.communityExists(user, community))) { + await this.deleteCommunity(community.url) + return null + } return await this.syncCommunity(user, community) } @@ -106,7 +153,11 @@ export class CommunityService extends AbstractCommunityService { const user = await this.userService.getUser() if (user == null) return [] const allCommunities = await this.db.select().from(communities) - const syncCommunities = allCommunities.map((c) => { + const existingCommunities = await this.removeNonExistentCommunities( + user, + allCommunities, + ) + const syncCommunities = existingCommunities.map((c) => { return this.syncCommunity(user, c) }) return await Promise.all(syncCommunities) diff --git a/src/electron/services/GitHubService.ts b/src/electron/services/GitHubService.ts index d31965c..96ddf89 100644 --- a/src/electron/services/GitHubService.ts +++ b/src/electron/services/GitHubService.ts @@ -237,6 +237,36 @@ export class GitHubService { ) } + public doesRepoExist = async ({ + repoName, + username, + token, + }: GetRepoInfoArgs): Promise => { + try { + await this.getRepoInfo({ + repoName: repoName, + username: username, + token: token, + }) + return true + } catch (ex: any) { + if (ex instanceof Error) { + try { + const error = JSON.parse(ex.message) + if ('status' in error && error.status === 404) { + return false + } else { + throw ex + } + } catch (error) { + throw ex + } + } else { + throw new Error(`${ex}`) + } + } + } + public getDefaultBranch = async (args: GetRepoInfoArgs) => { try { const response = await this.getRepoInfo(args) diff --git a/src/electron/services/ValidationService.ts b/src/electron/services/ValidationService.ts index 5e56980..d6c60a2 100644 --- a/src/electron/services/ValidationService.ts +++ b/src/electron/services/ValidationService.ts @@ -96,29 +96,11 @@ export class ValidationService extends AbstractValidationService { ): Promise => { const repoSegments = urlToRepoSegments(repoUrl) - try { - await this.gitHubService.getRepoInfo({ - repoName: repoSegments.repo, - username: repoSegments.owner, - token: user.pat, - }) - return true - } catch (ex: any) { - if (ex instanceof Error) { - try { - const error = JSON.parse(ex.message) - if ('status' in error && error.status === 404) { - return false - } else { - throw ex - } - } catch (error) { - throw ex - } - } else { - throw new Error(`${ex}`) - } - } + return this.gitHubService.doesRepoExist({ + repoName: repoSegments.repo, + username: repoSegments.owner, + token: user.pat, + }) } private validateIdRepos = async (