From f678ab6077dda1d93f5d24f8af3ab230221bcc3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=B8vring?= Date: Tue, 7 Nov 2023 09:02:38 +0100 Subject: [PATCH] Simplifies project interface # Conflicts: # src/composition.ts --- .../common/authHandler/logoutHandler.test.ts | 12 +++--- .../projects/CachingProjectDataSource.test.ts | 6 +-- src/app/[...slug]/page.tsx | 4 +- src/app/api/auth/[auth0]/route.ts | 4 +- src/app/page.tsx | 6 +-- src/common/authHandler/logout.ts | 6 +-- src/composition.ts | 18 ++++----- .../domain/CachingProjectDataSource.ts | 10 ++--- .../projects/domain/IProjectRepository.ts | 5 ++- .../domain/ISessionProjectRepository.ts | 7 ---- .../projects/domain/ProjectRepository.ts | 37 +++++++++++++++++++ .../domain/SessionProjectRepository.ts | 29 --------------- src/features/projects/view/ProjectsPage.tsx | 8 ++-- 13 files changed, 75 insertions(+), 77 deletions(-) delete mode 100644 src/features/projects/domain/ISessionProjectRepository.ts create mode 100644 src/features/projects/domain/ProjectRepository.ts delete mode 100644 src/features/projects/domain/SessionProjectRepository.ts diff --git a/__test__/common/authHandler/logoutHandler.test.ts b/__test__/common/authHandler/logoutHandler.test.ts index 49bd48e4..8060eb45 100644 --- a/__test__/common/authHandler/logoutHandler.test.ts +++ b/__test__/common/authHandler/logoutHandler.test.ts @@ -11,11 +11,11 @@ test("It deletes the user's auth token", async () => { didDeleteAuthToken = true } }, { - async getProjects() { + async get() { return [] }, - async storeProjects() {}, - async deleteProjects() {} + async set() {}, + async delete() {} }) expect(didDeleteAuthToken).toBeTruthy() }) @@ -29,11 +29,11 @@ test("It deletes the cached projects", async () => { async storeOAuthToken() {}, async deleteOAuthToken() {} }, { - async getProjects() { + async get() { return [] }, - async storeProjects() {}, - async deleteProjects() { + async set() {}, + async delete() { didDeleteProjects = true } }) diff --git a/__test__/projects/CachingProjectDataSource.test.ts b/__test__/projects/CachingProjectDataSource.test.ts index f92efe23..1a0f2f76 100644 --- a/__test__/projects/CachingProjectDataSource.test.ts +++ b/__test__/projects/CachingProjectDataSource.test.ts @@ -32,13 +32,13 @@ test("It caches projects read from the data source", async () => { return projects } }, { - async getProjects() { + async get() { return [] }, - async storeProjects(projects) { + async set(projects) { cachedProjects = projects }, - async deleteProjects() {} + async delete() {} }) await sut.getProjects() expect(cachedProjects).toEqual(projects) diff --git a/src/app/[...slug]/page.tsx b/src/app/[...slug]/page.tsx index ba172ad2..2193779a 100644 --- a/src/app/[...slug]/page.tsx +++ b/src/app/[...slug]/page.tsx @@ -1,7 +1,7 @@ import { getProjectId, getSpecificationId, getVersionId } from "@/common/utils/url" import SessionOAuthTokenBarrier from "@/features/auth/view/SessionOAuthTokenBarrier" import ProjectsPage from "@/features/projects/view/ProjectsPage" -import { sessionProjectRepository } from "@/composition" +import { projectRepository } from "@/composition" type PageParams = { slug: string | string[] } @@ -10,7 +10,7 @@ export default async function Page({ params }: { params: PageParams }) { return ( { const onLogout: NextAppRouterHandler = async (req: NextRequest, ctx: AppRouteHandlerFnContext) => { await Promise.all([ sessionOAuthTokenRepository.deleteOAuthToken().catch(() => null), - sessionProjectRepository.deleteProjects().catch(() => null) + projectRepository.delete().catch(() => null) ]) await logoutHandler() return await handleLogout(req, ctx) diff --git a/src/app/page.tsx b/src/app/page.tsx index a72a8f99..9fcd36ad 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,13 +1,11 @@ import SessionOAuthTokenBarrier from "@/features/auth/view/SessionOAuthTokenBarrier" import ProjectsPage from "@/features/projects/view/ProjectsPage" -import { sessionProjectRepository } from "@/composition" +import { projectRepository } from "@/composition" export default async function Page() { return ( - + ) } diff --git a/src/common/authHandler/logout.ts b/src/common/authHandler/logout.ts index 9bc80634..34d9a611 100644 --- a/src/common/authHandler/logout.ts +++ b/src/common/authHandler/logout.ts @@ -1,12 +1,12 @@ import ISessionOAuthTokenRepository from "@/features/auth/domain/ISessionOAuthTokenRepository" -import ISessionProjectRepository from "@/features/projects/domain/ISessionProjectRepository" +import IProjectRepository from "@/features/projects/domain/IProjectRepository" export default async function logoutHandler( sessionOAuthTokenRepository: ISessionOAuthTokenRepository, - sessionProjectRepository: ISessionProjectRepository + projectRepository: IProjectRepository ) { await Promise.all([ sessionOAuthTokenRepository.deleteOAuthToken().catch(() => null), - sessionProjectRepository.deleteProjects().catch(() => null) + projectRepository.delete().catch(() => null) ]) } diff --git a/src/composition.ts b/src/composition.ts index dcfac50c..b464ff06 100644 --- a/src/composition.ts +++ b/src/composition.ts @@ -9,13 +9,13 @@ import GitHubProjectDataSource from "@/features/projects/data/GitHubProjectDataS import InitialOAuthTokenService from "@/features/auth/domain/InitialOAuthTokenService" import KeyValueUserDataRepository from "@/common/userData/KeyValueUserDataRepository" import LockingAccessTokenRefresher from "@/features/auth/domain/LockingAccessTokenRefresher" +import ProjectRepository from "@/features/projects/domain/ProjectRepository" import RedisKeyedMutexFactory from "@/common/mutex/RedisKeyedMutexFactory" import RedisKeyValueStore from "@/common/keyValueStore/RedisKeyValueStore" import SessionAccessTokenReader from "@/features/auth/domain/SessionAccessTokenReader" import SessionDataRepository from "@/common/userData/SessionDataRepository" import SessionMutexFactory from "@/common/mutex/SessionMutexFactory" import SessionOAuthTokenRepository from "@/features/auth/domain/SessionOAuthTokenRepository" -import SessionProjectRepository from "@/features/projects/domain/SessionProjectRepository" import SessionValidatingProjectDataSource from "@/features/projects/domain/SessionValidatingProjectDataSource" import OAuthTokenRepository from "@/features/auth/domain/OAuthTokenRepository" import authLogoutHandler from "@/common/authHandler/logout" @@ -77,13 +77,11 @@ export const sessionValidator = new GitHubOrganizationSessionValidator( GITHUB_ORGANIZATION_NAME ) -export const sessionProjectRepository = new SessionProjectRepository( - new SessionDataRepository( - new Auth0Session(), - new KeyValueUserDataRepository( - new RedisKeyValueStore(REDIS_URL), - "projects" - ) +export const projectRepository = new ProjectRepository( + new Auth0Session(), + new KeyValueUserDataRepository( + new RedisKeyValueStore(REDIS_URL), + "projects" ) ) @@ -95,7 +93,7 @@ export const projectDataSource = new CachingProjectDataSource( GITHUB_ORGANIZATION_NAME ) ), - sessionProjectRepository + projectRepository ) export const initialOAuthTokenService = new InitialOAuthTokenService({ @@ -110,5 +108,5 @@ export const initialOAuthTokenService = new InitialOAuthTokenService({ }) export const logoutHandler = async () => { - await authLogoutHandler(sessionOAuthTokenRepository, sessionProjectRepository) + await authLogoutHandler(sessionOAuthTokenRepository, projectRepository) } diff --git a/src/features/projects/domain/CachingProjectDataSource.ts b/src/features/projects/domain/CachingProjectDataSource.ts index f076ae7d..a95dae13 100644 --- a/src/features/projects/domain/CachingProjectDataSource.ts +++ b/src/features/projects/domain/CachingProjectDataSource.ts @@ -1,22 +1,22 @@ import Project from "./Project" import IProjectDataSource from "./IProjectDataSource" -import ISessionProjectRepository from "./ISessionProjectRepository" +import IProjectRepository from "./IProjectRepository" export default class CachingProjectDataSource implements IProjectDataSource { private dataSource: IProjectDataSource - private sessionProjectRepository: ISessionProjectRepository + private repository: IProjectRepository constructor( dataSource: IProjectDataSource, - sessionProjectRepository: ISessionProjectRepository + repository: IProjectRepository ) { this.dataSource = dataSource - this.sessionProjectRepository = sessionProjectRepository + this.repository = repository } async getProjects(): Promise { const projects = await this.dataSource.getProjects() - await this.sessionProjectRepository.storeProjects(projects) + await this.repository.set(projects) return projects } } \ No newline at end of file diff --git a/src/features/projects/domain/IProjectRepository.ts b/src/features/projects/domain/IProjectRepository.ts index a123d92e..52a4af69 100644 --- a/src/features/projects/domain/IProjectRepository.ts +++ b/src/features/projects/domain/IProjectRepository.ts @@ -1,6 +1,7 @@ import Project from "./Project" export default interface IProjectRepository { - getProjects(): Promise - storeProjects(projects: Project[]): Promise + get(): Promise + set(projects: Project[]): Promise + delete(): Promise } diff --git a/src/features/projects/domain/ISessionProjectRepository.ts b/src/features/projects/domain/ISessionProjectRepository.ts deleted file mode 100644 index 055b78e7..00000000 --- a/src/features/projects/domain/ISessionProjectRepository.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Project from "./Project" - -export default interface ISessionProjectRepository { - getProjects(): Promise - storeProjects(projects: Project[]): Promise - deleteProjects(): Promise -} diff --git a/src/features/projects/domain/ProjectRepository.ts b/src/features/projects/domain/ProjectRepository.ts new file mode 100644 index 00000000..356c4a53 --- /dev/null +++ b/src/features/projects/domain/ProjectRepository.ts @@ -0,0 +1,37 @@ +import ZodJSONCoder from "@/common/utils/ZodJSONCoder" +import ISession from "@/common/session/ISession" +import IUserDataRepository from "@/common/userData/IUserDataRepository" +import IProjectRepository from "./IProjectRepository" +import Project, { ProjectSchema } from "./Project" + +type Repository = IUserDataRepository + +export default class ProjectRepository implements IProjectRepository { + private readonly session: ISession + private readonly repository: Repository + + constructor(session: ISession, repository: Repository) { + this.session = session + this.repository = repository + } + + async get(): Promise { + const userId = await this.session.getUserId() + const string = await this.repository.get(userId) + if (!string) { + return undefined + } + return ZodJSONCoder.decode(ProjectSchema.array(), string) + } + + async set(projects: Project[]): Promise { + const userId = await this.session.getUserId() + const string = ZodJSONCoder.encode(ProjectSchema.array(), projects) + await this.repository.set(userId, string) + } + + async delete(): Promise { + const userId = await this.session.getUserId() + await this.repository.delete(userId) + } +} diff --git a/src/features/projects/domain/SessionProjectRepository.ts b/src/features/projects/domain/SessionProjectRepository.ts deleted file mode 100644 index 5387a3c5..00000000 --- a/src/features/projects/domain/SessionProjectRepository.ts +++ /dev/null @@ -1,29 +0,0 @@ -import ZodJSONCoder from "@/common/utils/ZodJSONCoder" -import ISessionDataRepository from "@/common/userData/ISessionDataRepository" -import ISessionProjectRepository from "./ISessionProjectRepository" -import Project, { ProjectSchema } from "./Project" - -export default class SessionProjectRepository implements ISessionProjectRepository { - private readonly repository: ISessionDataRepository - - constructor(repository: ISessionDataRepository) { - this.repository = repository - } - - async getProjects(): Promise { - const string = await this.repository.get() - if (!string) { - return undefined - } - return ZodJSONCoder.decode(ProjectSchema.array(), string) - } - - async storeProjects(projects: Project[]): Promise { - const string = ZodJSONCoder.encode(ProjectSchema.array(), projects) - await this.repository.set(string) - } - - async deleteProjects(): Promise { - await this.repository.delete() - } -} diff --git a/src/features/projects/view/ProjectsPage.tsx b/src/features/projects/view/ProjectsPage.tsx index 37c41cfe..d4369eac 100644 --- a/src/features/projects/view/ProjectsPage.tsx +++ b/src/features/projects/view/ProjectsPage.tsx @@ -1,18 +1,18 @@ -import SessionProjectRepository from "../domain/SessionProjectRepository" +import ProjectRepository from "../domain/ProjectRepository" import ClientProjectsPage from "./client/ProjectsPage" export default async function ProjectsPage({ - sessionProjectRepository, + projectRepository, projectId, versionId, specificationId }: { - sessionProjectRepository: SessionProjectRepository + projectRepository: ProjectRepository projectId?: string versionId?: string specificationId?: string }) { - const projects = await sessionProjectRepository.getProjects() + const projects = await projectRepository.get() return (