Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions __test__/common/authHandler/logoutHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
Expand All @@ -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
}
})
Expand Down
6 changes: 3 additions & 3 deletions __test__/projects/CachingProjectDataSource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/app/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -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[] }

Expand All @@ -10,7 +10,7 @@ export default async function Page({ params }: { params: PageParams }) {
return (
<SessionOAuthTokenBarrier>
<ProjectsPage
sessionProjectRepository={sessionProjectRepository}
projectRepository={projectRepository}
projectId={getProjectId(url)}
versionId={getVersionId(url)}
specificationId={getSpecificationId(url)}
Expand Down
4 changes: 2 additions & 2 deletions src/app/api/auth/[auth0]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import {
initialOAuthTokenService,
sessionOAuthTokenRepository,
sessionProjectRepository,
projectRepository,
logoutHandler
} from "@/composition"

Expand All @@ -30,7 +30,7 @@ const onError: AppRouterOnError = async () => {
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)
Expand Down
6 changes: 2 additions & 4 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<SessionOAuthTokenBarrier>
<ProjectsPage
sessionProjectRepository={sessionProjectRepository}
/>
<ProjectsPage projectRepository={projectRepository} />
</SessionOAuthTokenBarrier>
)
}
6 changes: 3 additions & 3 deletions src/common/authHandler/logout.ts
Original file line number Diff line number Diff line change
@@ -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)
])
}
18 changes: 8 additions & 10 deletions src/composition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
)
)

Expand All @@ -95,7 +93,7 @@ export const projectDataSource = new CachingProjectDataSource(
GITHUB_ORGANIZATION_NAME
)
),
sessionProjectRepository
projectRepository
)

export const initialOAuthTokenService = new InitialOAuthTokenService({
Expand All @@ -110,5 +108,5 @@ export const initialOAuthTokenService = new InitialOAuthTokenService({
})

export const logoutHandler = async () => {
await authLogoutHandler(sessionOAuthTokenRepository, sessionProjectRepository)
await authLogoutHandler(sessionOAuthTokenRepository, projectRepository)
}
10 changes: 5 additions & 5 deletions src/features/projects/domain/CachingProjectDataSource.ts
Original file line number Diff line number Diff line change
@@ -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<Project[]> {
const projects = await this.dataSource.getProjects()
await this.sessionProjectRepository.storeProjects(projects)
await this.repository.set(projects)
return projects
}
}
5 changes: 3 additions & 2 deletions src/features/projects/domain/IProjectRepository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Project from "./Project"

export default interface IProjectRepository {
getProjects(): Promise<Project[]>
storeProjects(projects: Project[]): Promise<void>
get(): Promise<Project[] | undefined>
set(projects: Project[]): Promise<void>
delete(): Promise<void>
}
7 changes: 0 additions & 7 deletions src/features/projects/domain/ISessionProjectRepository.ts

This file was deleted.

37 changes: 37 additions & 0 deletions src/features/projects/domain/ProjectRepository.ts
Original file line number Diff line number Diff line change
@@ -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<string>

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<Project[] | undefined> {
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<void> {
const userId = await this.session.getUserId()
const string = ZodJSONCoder.encode(ProjectSchema.array(), projects)
await this.repository.set(userId, string)
}

async delete(): Promise<void> {
const userId = await this.session.getUserId()
await this.repository.delete(userId)
}
}
29 changes: 0 additions & 29 deletions src/features/projects/domain/SessionProjectRepository.ts

This file was deleted.

8 changes: 4 additions & 4 deletions src/features/projects/view/ProjectsPage.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<ClientProjectsPage
projects={projects}
Expand Down