diff --git a/pkg/intermodule/account.ts b/pkg/intermodule/account.ts index 5b895cc8..4aba57d1 100644 --- a/pkg/intermodule/account.ts +++ b/pkg/intermodule/account.ts @@ -1,11 +1,24 @@ import { Result } from '@mikuroxina/mini-fn'; +import { Cat, Ether } from '@mikuroxina/mini-fn'; +import { + InMemoryAccountRepository, + newFollowRepo, +} from '../accounts/adaptor/repository/dummy.js'; +import { + PrismaAccountRepository, + prismaFollowRepo, +} from '../accounts/adaptor/repository/prisma.js'; import type { Account, AccountID, AccountName, } from '../accounts/model/account.js'; +import { accountRepoSymbol } from '../accounts/model/repository.js'; import type { FetchService } from '../accounts/service/fetch.js'; +import { fetch } from '../accounts/service/fetch.js'; import type { FetchFollowService } from '../accounts/service/fetchFollow.js'; +import { fetchFollow } from '../accounts/service/fetchFollow.js'; +import { prismaClient } from '../adaptors/prisma.js'; export type { Account } from '../accounts/model/account.js'; @@ -84,3 +97,41 @@ export class AccountModuleFacade { ); } } + +const isProduction = process.env.NODE_ENV === 'production'; +const accountRepoObject = isProduction + ? new PrismaAccountRepository(prismaClient) + : new InMemoryAccountRepository([]); +const accountRepository = Ether.newEther( + accountRepoSymbol, + () => accountRepoObject, +); + +const accountFollowRepository = isProduction + ? prismaFollowRepo(prismaClient) + : newFollowRepo(); + +export const accountModule = new AccountModuleFacade( + Ether.runEther(Cat.cat(fetch).feed(Ether.compose(accountRepository)).value), + Ether.runEther( + Cat.cat(fetchFollow) + .feed(Ether.compose(accountFollowRepository)) + .feed(Ether.compose(accountRepository)).value, + ), +); + +const inMemoryAccountRepository = Ether.newEther( + accountRepoSymbol, + () => new InMemoryAccountRepository([]), +); +const inMemoryFollowRepository = newFollowRepo(); +export const dummyAccountModuleFacade = new AccountModuleFacade( + Ether.runEther( + Cat.cat(fetch).feed(Ether.compose(inMemoryAccountRepository)).value, + ), + Ether.runEther( + Cat.cat(fetchFollow) + .feed(Ether.compose(inMemoryFollowRepository)) + .feed(Ether.compose(inMemoryAccountRepository)).value, + ), +); diff --git a/pkg/notes/mod.ts b/pkg/notes/mod.ts index 207b2548..2bbe6a9a 100644 --- a/pkg/notes/mod.ts +++ b/pkg/notes/mod.ts @@ -1,19 +1,8 @@ import { OpenAPIHono } from '@hono/zod-openapi'; import { Cat, Ether, Promise, Result } from '@mikuroxina/mini-fn'; -import { - InMemoryAccountRepository, - newFollowRepo, -} from '../accounts/adaptor/repository/dummy.js'; -import { - PrismaAccountRepository, - prismaFollowRepo, -} from '../accounts/adaptor/repository/prisma.js'; import type { AccountID } from '../accounts/model/account.js'; -import { accountRepoSymbol } from '../accounts/model/repository.js'; import { authenticateToken } from '../accounts/service/authenticationTokenService.js'; -import { fetch } from '../accounts/service/fetch.js'; -import { fetchFollow } from '../accounts/service/fetchFollow.js'; import { type AuthMiddlewareVariable, authenticateMiddleware, @@ -21,7 +10,7 @@ import { import { prismaClient } from '../adaptors/prisma.js'; import { SnowflakeIDGenerator } from '../id/mod.js'; import type { ID } from '../id/type.js'; -import { AccountModuleFacade } from '../intermodule/account.js'; +import { accountModule } from '../intermodule/account.js'; import { BookmarkController } from './adaptor/controller/bookmark.js'; import { NoteController } from './adaptor/controller/note.js'; import { @@ -78,28 +67,6 @@ const AuthMiddleware = await Ether.runEtherT( ).value, ); -// Account -const accountRepoObject = isProduction - ? new PrismaAccountRepository(prismaClient) - : new InMemoryAccountRepository([]); -const accountRepository = Ether.newEther( - accountRepoSymbol, - () => accountRepoObject, -); - -const accountFollowRepository = isProduction - ? prismaFollowRepo(prismaClient) - : newFollowRepo(); - -const accountModule = new AccountModuleFacade( - Ether.runEther(Cat.cat(fetch).feed(Ether.compose(accountRepository)).value), - Ether.runEther( - Cat.cat(fetchFollow) - .feed(Ether.compose(accountFollowRepository)) - .feed(Ether.compose(accountRepository)).value, - ), -); - // Note const createService = new CreateService( noteRepository, diff --git a/pkg/notes/service/fetch.test.ts b/pkg/notes/service/fetch.test.ts index a8f6d576..9245c298 100644 --- a/pkg/notes/service/fetch.test.ts +++ b/pkg/notes/service/fetch.test.ts @@ -1,14 +1,9 @@ import { Option, Result } from '@mikuroxina/mini-fn'; import { afterEach, describe, expect, it, vi } from 'vitest'; -import { - InMemoryAccountFollowRepository, - InMemoryAccountRepository, -} from '../../accounts/adaptor/repository/dummy.js'; +import { InMemoryAccountRepository } from '../../accounts/adaptor/repository/dummy.js'; import { Account, type AccountID } from '../../accounts/model/account.js'; -import { FetchService as AccountFetchService } from '../../accounts/service/fetch.js'; -import { FetchFollowService } from '../../accounts/service/fetchFollow.js'; -import { AccountModuleFacade } from '../../intermodule/account.js'; +import { dummyAccountModuleFacade } from '../../intermodule/account.js'; import { InMemoryNoteRepository } from '../adaptor/repository/dummy.js'; import { Note, type NoteID } from '../model/note.js'; import { FetchService } from './fetch.js'; @@ -90,20 +85,17 @@ const accountRepository = new InMemoryAccountRepository([ testAccount, frozenAccount, ]); -const accountFollowRepository = new InMemoryAccountFollowRepository(); -const accountModule = new AccountModuleFacade( - new AccountFetchService(accountRepository), - new FetchFollowService(accountFollowRepository, accountRepository), -); -const service = new FetchService(repository, accountModule); +const service = new FetchService(repository, dummyAccountModuleFacade); describe('FetchService', () => { afterEach(() => accountRepository.reset()); it('should fetch notes', async () => { - vi.spyOn(accountModule, 'fetchAccount').mockImplementation(async () => { - return Result.ok(testAccount); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchAccount').mockImplementation( + async () => { + return Result.ok(testAccount); + }, + ); const res = await service.fetchNoteByID('1' as NoteID); expect(Option.isSome(res)).toBe(true); @@ -123,9 +115,11 @@ describe('FetchService', () => { }); it('account frozen', async () => { - vi.spyOn(accountModule, 'fetchAccount').mockImplementation(async () => { - return Result.ok(frozenAccount); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchAccount').mockImplementation( + async () => { + return Result.ok(frozenAccount); + }, + ); const res = await service.fetchNoteByID(frozenUserNote.getID()); expect(Option.isNone(res)).toBe(true); diff --git a/pkg/timeline/mod.ts b/pkg/timeline/mod.ts index d8f35133..c1119c28 100644 --- a/pkg/timeline/mod.ts +++ b/pkg/timeline/mod.ts @@ -1,15 +1,9 @@ import { OpenAPIHono } from '@hono/zod-openapi'; import { Option, Result } from '@mikuroxina/mini-fn'; -import { - InMemoryAccountFollowRepository, - InMemoryAccountRepository, -} from '../accounts/adaptor/repository/dummy.js'; import type { AccountID } from '../accounts/model/account.js'; -import { FetchService as AccountFetchService } from '../accounts/service/fetch.js'; -import { FetchFollowService } from '../accounts/service/fetchFollow.js'; import { SnowflakeIDGenerator } from '../id/mod.js'; -import { AccountModuleFacade } from '../intermodule/account.js'; +import { accountModule } from '../intermodule/account.js'; import { Note, type NoteID } from '../notes/model/note.js'; import { TimelineController } from './adaptor/controller/timeline.js'; import { @@ -33,12 +27,6 @@ const idGenerator = new SnowflakeIDGenerator(0, { now: () => BigInt(Date.now()), }); -const accountRepository = new InMemoryAccountRepository([]); -const accountFollowRepository = new InMemoryAccountFollowRepository(); -const accountModule = new AccountModuleFacade( - new AccountFetchService(accountRepository), - new FetchFollowService(accountFollowRepository, accountRepository), -); const timelineRepository = new InMemoryTimelineRepository(); const listRepository = new InMemoryListRepository(); const timelineNotesCacheRepository = new InMemoryTimelineCacheRepository(); diff --git a/pkg/timeline/service/account.test.ts b/pkg/timeline/service/account.test.ts index 33113de8..f86609f7 100644 --- a/pkg/timeline/service/account.test.ts +++ b/pkg/timeline/service/account.test.ts @@ -1,14 +1,8 @@ import { Option, Result } from '@mikuroxina/mini-fn'; import { describe, expect, it, vi } from 'vitest'; -import { - InMemoryAccountFollowRepository, - InMemoryAccountRepository, -} from '../../accounts/adaptor/repository/dummy.js'; import { Account, type AccountID } from '../../accounts/model/account.js'; -import { FetchService as AccountFetchService } from '../../accounts/service/fetch.js'; -import { FetchFollowService } from '../../accounts/service/fetchFollow.js'; -import { AccountModuleFacade } from '../../intermodule/account.js'; +import { dummyAccountModuleFacade } from '../../intermodule/account.js'; import type { PartialAccount } from '../../intermodule/account.js'; import { Note, type NoteID } from '../../notes/model/note.js'; import { InMemoryTimelineRepository } from '../adaptor/repository/dummy.js'; @@ -16,13 +10,9 @@ import { AccountTimelineService } from './account.js'; import { NoteVisibilityService } from './noteVisibility.js'; describe('AccountTimelineService', () => { - const accountRepository = new InMemoryAccountRepository([]); - const accountFollowRepository = new InMemoryAccountFollowRepository(); - const accountModule = new AccountModuleFacade( - new AccountFetchService(accountRepository), - new FetchFollowService(accountFollowRepository, accountRepository), + const noteVisibilityService = new NoteVisibilityService( + dummyAccountModuleFacade, ); - const noteVisibilityService = new NoteVisibilityService(accountModule); const dummyPublicNote = Note.new({ id: '1' as NoteID, @@ -100,9 +90,11 @@ describe('AccountTimelineService', () => { }); it('if following', async () => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => { - return Result.ok([partialAccount1]); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => { + return Result.ok([partialAccount1]); + }, + ); const res = await accountTimelineService.handle('100' as AccountID, { id: '101' as AccountID, hasAttachment: false, @@ -118,9 +110,11 @@ describe('AccountTimelineService', () => { }); it('if not following', async () => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => { - return Result.ok([partialAccount1]); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => { + return Result.ok([partialAccount1]); + }, + ); const res = await accountTimelineService.handle('100' as AccountID, { id: '0' as AccountID, hasAttachment: false, diff --git a/pkg/timeline/service/noteVisibility.test.ts b/pkg/timeline/service/noteVisibility.test.ts index b42a52db..7bdbb4c2 100644 --- a/pkg/timeline/service/noteVisibility.test.ts +++ b/pkg/timeline/service/noteVisibility.test.ts @@ -1,14 +1,8 @@ import { Result } from '@mikuroxina/mini-fn'; import { describe, expect, it, vi } from 'vitest'; -import { - InMemoryAccountFollowRepository, - InMemoryAccountRepository, -} from '../../accounts/adaptor/repository/dummy.js'; import type { AccountID } from '../../accounts/model/account.js'; -import { FetchService as AccountFetchService } from '../../accounts/service/fetch.js'; -import { FetchFollowService } from '../../accounts/service/fetchFollow.js'; -import { AccountModuleFacade } from '../../intermodule/account.js'; +import { dummyAccountModuleFacade } from '../../intermodule/account.js'; import { dummyDirectNote, dummyFollowersNote, @@ -19,18 +13,14 @@ import { import { NoteVisibilityService } from './noteVisibility.js'; describe('NoteVisibilityService', () => { - const accountRepository = new InMemoryAccountRepository([]); - const accountFollowRepository = new InMemoryAccountFollowRepository(); - const accountModule = new AccountModuleFacade( - new AccountFetchService(accountRepository), - new FetchFollowService(accountFollowRepository, accountRepository), - ); - const visibilityService = new NoteVisibilityService(accountModule); + const visibilityService = new NoteVisibilityService(dummyAccountModuleFacade); it("when author's note: return true", async () => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => { - return Result.ok([partialAccount1]); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => { + return Result.ok([partialAccount1]); + }, + ); const testObjects = [ dummyPublicNote, @@ -49,9 +39,11 @@ describe('NoteVisibilityService', () => { }); it('when direct note: return true if sendTo is accountID', async () => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => { - return Result.ok([partialAccount1]); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => { + return Result.ok([partialAccount1]); + }, + ); const res = await visibilityService.handle({ accountID: '101' as AccountID, @@ -67,9 +59,11 @@ describe('NoteVisibilityService', () => { }); it('when following: return true if public,home,followers', async () => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => { - return Result.ok([partialAccount1]); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => { + return Result.ok([partialAccount1]); + }, + ); // public expect( await visibilityService.handle({ @@ -94,9 +88,11 @@ describe('NoteVisibilityService', () => { }); it('when not following: return true if public, home', async () => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => { - return Result.ok([partialAccount1]); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => { + return Result.ok([partialAccount1]); + }, + ); expect( await visibilityService.handle({ @@ -120,9 +116,11 @@ describe('NoteVisibilityService', () => { }); it('always return true if public', async () => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => { - return Result.ok([partialAccount1]); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => { + return Result.ok([partialAccount1]); + }, + ); const res = await visibilityService.handle({ accountID: '0' as AccountID, @@ -132,8 +130,8 @@ describe('NoteVisibilityService', () => { }); it("homeTimelineVisibilityCheck: return true if visibility is not 'DIRECT'", async () => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => - Result.ok([partialAccount1]), + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => Result.ok([partialAccount1]), ); expect( diff --git a/pkg/timeline/service/push.test.ts b/pkg/timeline/service/push.test.ts index f38f36e8..d337051e 100644 --- a/pkg/timeline/service/push.test.ts +++ b/pkg/timeline/service/push.test.ts @@ -1,37 +1,27 @@ import { Result } from '@mikuroxina/mini-fn'; import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { - InMemoryAccountFollowRepository, - InMemoryAccountRepository, -} from '../../accounts/adaptor/repository/dummy.js'; -import { FetchService as AccountFetchService } from '../../accounts/service/fetch.js'; -import { FetchFollowService } from '../../accounts/service/fetchFollow.js'; -import { AccountModuleFacade } from '../../intermodule/account.js'; +import { dummyAccountModuleFacade } from '../../intermodule/account.js'; import { InMemoryTimelineCacheRepository } from '../adaptor/repository/dummyCache.js'; import { dummyPublicNote, partialAccount1 } from '../testData/testData.js'; import { NoteVisibilityService } from './noteVisibility.js'; import { PushTimelineService } from './push.js'; describe('PushTimelineService', () => { - const accountRepository = new InMemoryAccountRepository([]); - const accountFollowRepository = new InMemoryAccountFollowRepository(); - const accountModule = new AccountModuleFacade( - new AccountFetchService(accountRepository), - new FetchFollowService(accountFollowRepository, accountRepository), - ); - const noteVisibility = new NoteVisibilityService(accountModule); + const noteVisibility = new NoteVisibilityService(dummyAccountModuleFacade); const timelineCacheRepository = new InMemoryTimelineCacheRepository(); const pushTimelineService = new PushTimelineService( - accountModule, + dummyAccountModuleFacade, noteVisibility, timelineCacheRepository, ); beforeEach(() => { - vi.spyOn(accountModule, 'fetchFollowers').mockImplementation(async () => { - return Result.ok([partialAccount1]); - }); + vi.spyOn(dummyAccountModuleFacade, 'fetchFollowers').mockImplementation( + async () => { + return Result.ok([partialAccount1]); + }, + ); }); it('push to home timeline', async () => {