From af5ecfcba486fecf657bf0d9c62d64b494971751 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 11:54:21 +0900 Subject: [PATCH 01/19] =?UTF-8?q?refactor:=20=EC=9D=B8=EC=A6=9D=20provider?= =?UTF-8?q?=EB=B3=84=20protocol=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application/Data/Sources/DataAssembler.swift | 12 ++++++------ .../Sources/Protocol/AuthenticationService.swift | 6 ++++++ .../Sources/Repository/AuthDataRepositoryImpl.swift | 12 ++++++------ .../Repository/AuthenticationRepositoryImpl.swift | 12 ++++++------ .../AuthenticationRepositoryImplTests.swift | 5 ++++- Application/Infra/Sources/InfraAssembler.swift | 6 +++--- .../SocialLogin/AppleAuthenticationServiceImpl.swift | 2 +- .../GithubAuthenticationServiceImpl.swift | 2 +- .../GoogleAuthenticationServiceImpl.swift | 2 +- 9 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Application/Data/Sources/DataAssembler.swift b/Application/Data/Sources/DataAssembler.swift index c7f23fa2..5f3a1e51 100644 --- a/Application/Data/Sources/DataAssembler.swift +++ b/Application/Data/Sources/DataAssembler.swift @@ -16,15 +16,15 @@ public final class DataAssembler: Assembler { AuthenticationRepositoryImpl( authService: container.resolve(AuthService.self), appleAuthService: container.resolve( - AuthenticationService.self, + AppleAuthenticationService.self, name: "AppleAuthenticationService" ), githubAuthService: container.resolve( - AuthenticationService.self, + GithubAuthenticationService.self, name: "GithubAuthenticationService" ), googleAuthService: container.resolve( - AuthenticationService.self, + GoogleAuthenticationService.self, name: "GoogleAuthenticationService" ), userService: container.resolve(UserService.self), @@ -95,15 +95,15 @@ public final class DataAssembler: Assembler { AuthDataRepositoryImpl( authService: container.resolve(AuthService.self), appleAuthService: container.resolve( - AuthenticationService.self, + AppleAuthenticationService.self, name: "AppleAuthenticationService" ), githubAuthService: container.resolve( - AuthenticationService.self, + GithubAuthenticationService.self, name: "GithubAuthenticationService" ), googleAuthService: container.resolve( - AuthenticationService.self, + GoogleAuthenticationService.self, name: "GoogleAuthenticationService" ) ) diff --git a/Application/Data/Sources/Protocol/AuthenticationService.swift b/Application/Data/Sources/Protocol/AuthenticationService.swift index 71818cc3..8db8197b 100644 --- a/Application/Data/Sources/Protocol/AuthenticationService.swift +++ b/Application/Data/Sources/Protocol/AuthenticationService.swift @@ -14,3 +14,9 @@ public protocol AuthenticationService { func link(uid: String) async throws -> Bool func unlink(_ uid: String) async throws } + +public protocol AppleAuthenticationService: AuthenticationService { } + +public protocol GithubAuthenticationService: AuthenticationService { } + +public protocol GoogleAuthenticationService: AuthenticationService { } diff --git a/Application/Data/Sources/Repository/AuthDataRepositoryImpl.swift b/Application/Data/Sources/Repository/AuthDataRepositoryImpl.swift index 542d9f18..4b54ba35 100644 --- a/Application/Data/Sources/Repository/AuthDataRepositoryImpl.swift +++ b/Application/Data/Sources/Repository/AuthDataRepositoryImpl.swift @@ -9,15 +9,15 @@ import Domain final class AuthDataRepositoryImpl: AuthDataRepository { private let authService: AuthService - private let appleAuthService: AuthenticationService - private let githubAuthService: AuthenticationService - private let googleAuthService: AuthenticationService + private let appleAuthService: AppleAuthenticationService + private let githubAuthService: GithubAuthenticationService + private let googleAuthService: GoogleAuthenticationService init( authService: AuthService, - appleAuthService: AuthenticationService, - githubAuthService: AuthenticationService, - googleAuthService: AuthenticationService + appleAuthService: AppleAuthenticationService, + githubAuthService: GithubAuthenticationService, + googleAuthService: GoogleAuthenticationService ) { self.authService = authService self.appleAuthService = appleAuthService diff --git a/Application/Data/Sources/Repository/AuthenticationRepositoryImpl.swift b/Application/Data/Sources/Repository/AuthenticationRepositoryImpl.swift index f80bd7ce..529a4024 100644 --- a/Application/Data/Sources/Repository/AuthenticationRepositoryImpl.swift +++ b/Application/Data/Sources/Repository/AuthenticationRepositoryImpl.swift @@ -9,17 +9,17 @@ import Domain final class AuthenticationRepositoryImpl: AuthenticationRepository { private let authService: AuthService - private let appleAuthService: AuthenticationService - private let githubAuthService: AuthenticationService - private let googleAuthService: AuthenticationService + private let appleAuthService: AppleAuthenticationService + private let githubAuthService: GithubAuthenticationService + private let googleAuthService: GoogleAuthenticationService private let userService: UserService private let widgetSnapshotUpdater: WidgetSnapshotUpdater init( authService: AuthService, - appleAuthService: AuthenticationService, - githubAuthService: AuthenticationService, - googleAuthService: AuthenticationService, + appleAuthService: AppleAuthenticationService, + githubAuthService: GithubAuthenticationService, + googleAuthService: GoogleAuthenticationService, userService: UserService, widgetSnapshotUpdater: WidgetSnapshotUpdater ) { diff --git a/Application/Data/Tests/Repository/AuthenticationRepositoryImplTests.swift b/Application/Data/Tests/Repository/AuthenticationRepositoryImplTests.swift index c2f7868f..ac7097e3 100644 --- a/Application/Data/Tests/Repository/AuthenticationRepositoryImplTests.swift +++ b/Application/Data/Tests/Repository/AuthenticationRepositoryImplTests.swift @@ -269,7 +269,10 @@ final class AuthenticationRepositoryAuthServiceSpy: AuthService { } } -final class AuthenticationServiceSpy: AuthenticationService { +final class AuthenticationServiceSpy: + AppleAuthenticationService, + GithubAuthenticationService, + GoogleAuthenticationService { private let provider: String private let signInResult: Result private let linkResult: Result diff --git a/Application/Infra/Sources/InfraAssembler.swift b/Application/Infra/Sources/InfraAssembler.swift index 47e22b18..c59d8d62 100644 --- a/Application/Infra/Sources/InfraAssembler.swift +++ b/Application/Infra/Sources/InfraAssembler.swift @@ -29,21 +29,21 @@ public final class InfraAssembler: Assembler { } container.register( - AuthenticationService.self, + AppleAuthenticationService.self, name: "AppleAuthenticationService" ) { AppleAuthenticationServiceImpl() } container.register( - AuthenticationService.self, + GithubAuthenticationService.self, name: "GithubAuthenticationService" ) { GithubAuthenticationServiceImpl() } container.register( - AuthenticationService.self, + GoogleAuthenticationService.self, name: "GoogleAuthenticationService" ) { GoogleAuthenticationServiceImpl() diff --git a/Application/Infra/Sources/Service/SocialLogin/AppleAuthenticationServiceImpl.swift b/Application/Infra/Sources/Service/SocialLogin/AppleAuthenticationServiceImpl.swift index eaad706a..d1c50f6c 100644 --- a/Application/Infra/Sources/Service/SocialLogin/AppleAuthenticationServiceImpl.swift +++ b/Application/Infra/Sources/Service/SocialLogin/AppleAuthenticationServiceImpl.swift @@ -11,7 +11,7 @@ import Foundation import Core import Data -final class AppleAuthenticationServiceImpl: AuthenticationService { +final class AppleAuthenticationServiceImpl: AppleAuthenticationService { private enum CrashlyticsError { static let domain = "DevLogInfra.AppleAuthenticationServiceImpl" diff --git a/Application/Infra/Sources/Service/SocialLogin/GithubAuthenticationServiceImpl.swift b/Application/Infra/Sources/Service/SocialLogin/GithubAuthenticationServiceImpl.swift index 84ced79c..0a5e68dd 100644 --- a/Application/Infra/Sources/Service/SocialLogin/GithubAuthenticationServiceImpl.swift +++ b/Application/Infra/Sources/Service/SocialLogin/GithubAuthenticationServiceImpl.swift @@ -9,7 +9,7 @@ import FirebaseAuth import Core import Data -final class GithubAuthenticationServiceImpl: AuthenticationService { +final class GithubAuthenticationServiceImpl: GithubAuthenticationService { private enum CrashlyticsError { static let domain = "DevLogInfra.GithubAuthenticationServiceImpl" diff --git a/Application/Infra/Sources/Service/SocialLogin/GoogleAuthenticationServiceImpl.swift b/Application/Infra/Sources/Service/SocialLogin/GoogleAuthenticationServiceImpl.swift index bf848497..9725bd8d 100644 --- a/Application/Infra/Sources/Service/SocialLogin/GoogleAuthenticationServiceImpl.swift +++ b/Application/Infra/Sources/Service/SocialLogin/GoogleAuthenticationServiceImpl.swift @@ -11,7 +11,7 @@ import GoogleSignIn import Core import Data -final class GoogleAuthenticationServiceImpl: AuthenticationService { +final class GoogleAuthenticationServiceImpl: GoogleAuthenticationService { private enum CrashlyticsError { static let domain = "DevLogInfra.GoogleAuthenticationServiceImpl" From 5369808a1290be8253af039ba4540bf92fec8a39 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 12:06:05 +0900 Subject: [PATCH 02/19] =?UTF-8?q?chore:=20Cradle=201.2.0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Libraries/ThirdParty/Project.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Libraries/ThirdParty/Project.swift b/Libraries/ThirdParty/Project.swift index 5184c9ed..af00cf31 100644 --- a/Libraries/ThirdParty/Project.swift +++ b/Libraries/ThirdParty/Project.swift @@ -29,6 +29,10 @@ let project = Project( url: "https://github.com/apple/swift-collections.git", .exact("1.3.0") ), + .package( + url: "https://github.com/opficdev/Cradle.git", + .exact("1.2.0") + ), ], settings: .devlogProject(additionalBase: deploymentSettings), targets: [ @@ -63,6 +67,7 @@ let project = Project( .package(product: "Nexa"), .package(product: "ComposableArchitecture"), .package(product: "OrderedCollections"), + .package(product: "Cradle"), ], settings: .devlog( base: deploymentSettings From 62ef4a89f1c326e4bfb7b26b14a902172351652b Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 12:09:02 +0900 Subject: [PATCH 03/19] =?UTF-8?q?refactor:=20Infra=20provider=20graph=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Graph/AnalyticsServiceGraph.swift | 19 ++++++++++++++ .../Graph/AppStoreVersionServiceGraph.swift | 19 ++++++++++++++ .../AppleAuthenticationServiceGraph.swift | 19 ++++++++++++++ .../Sources/Graph/AuthServiceGraph.swift | 19 ++++++++++++++ .../Graph/DevelopmentGoalServiceGraph.swift | 19 ++++++++++++++ .../Graph/DevelopmentRecordServiceGraph.swift | 19 ++++++++++++++ .../Graph/FirebaseAppServiceGraph.swift | 19 ++++++++++++++ .../GithubAuthenticationServiceGraph.swift | 19 ++++++++++++++ .../GoogleAuthenticationServiceGraph.swift | 19 ++++++++++++++ .../NWPathConnectivityProviderGraph.swift | 19 ++++++++++++++ .../Graph/ProfileImageDataServiceGraph.swift | 19 ++++++++++++++ .../Graph/PushMessagingServiceGraph.swift | 19 ++++++++++++++ .../Graph/PushNotificationServiceGraph.swift | 19 ++++++++++++++ .../Graph/TodoCategoryServiceGraph.swift | 19 ++++++++++++++ .../Graph/TodoCommandServiceGraph.swift | 19 ++++++++++++++ .../Sources/Graph/TodoQueryServiceGraph.swift | 19 ++++++++++++++ .../Sources/Graph/UserServiceGraph.swift | 19 ++++++++++++++ .../Graph/WebPageMetadataServiceGraph.swift | 25 +++++++++++++++++++ .../Sources/Graph/WebPageServiceGraph.swift | 19 ++++++++++++++ 19 files changed, 367 insertions(+) create mode 100644 Application/Infra/Sources/Graph/AnalyticsServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/AppStoreVersionServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/AppleAuthenticationServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/AuthServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/DevelopmentGoalServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/DevelopmentRecordServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/FirebaseAppServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/GithubAuthenticationServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/GoogleAuthenticationServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/NWPathConnectivityProviderGraph.swift create mode 100644 Application/Infra/Sources/Graph/ProfileImageDataServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/PushMessagingServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/PushNotificationServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/TodoCategoryServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/TodoCommandServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/TodoQueryServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/UserServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/WebPageMetadataServiceGraph.swift create mode 100644 Application/Infra/Sources/Graph/WebPageServiceGraph.swift diff --git a/Application/Infra/Sources/Graph/AnalyticsServiceGraph.swift b/Application/Infra/Sources/Graph/AnalyticsServiceGraph.swift new file mode 100644 index 00000000..d4c5c5c7 --- /dev/null +++ b/Application/Infra/Sources/Graph/AnalyticsServiceGraph.swift @@ -0,0 +1,19 @@ +// +// AnalyticsServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class AnalyticsServiceGraph { + public init() { } + + @Provide + private func makeAnalyticsService() -> AnalyticsService { + FirebaseAnalyticsServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/AppStoreVersionServiceGraph.swift b/Application/Infra/Sources/Graph/AppStoreVersionServiceGraph.swift new file mode 100644 index 00000000..5f1732e0 --- /dev/null +++ b/Application/Infra/Sources/Graph/AppStoreVersionServiceGraph.swift @@ -0,0 +1,19 @@ +// +// AppStoreVersionServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class AppStoreVersionServiceGraph { + public init() { } + + @Provide + private func makeAppStoreVersionService() -> AppStoreVersionService { + ITunesAppVersionServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/AppleAuthenticationServiceGraph.swift b/Application/Infra/Sources/Graph/AppleAuthenticationServiceGraph.swift new file mode 100644 index 00000000..58919260 --- /dev/null +++ b/Application/Infra/Sources/Graph/AppleAuthenticationServiceGraph.swift @@ -0,0 +1,19 @@ +// +// AppleAuthenticationServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class AppleAuthenticationServiceGraph { + public init() { } + + @Provide + private func makeAppleAuthenticationService() -> AppleAuthenticationService { + AppleAuthenticationServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/AuthServiceGraph.swift b/Application/Infra/Sources/Graph/AuthServiceGraph.swift new file mode 100644 index 00000000..9493a1f7 --- /dev/null +++ b/Application/Infra/Sources/Graph/AuthServiceGraph.swift @@ -0,0 +1,19 @@ +// +// AuthServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class AuthServiceGraph { + public init() { } + + @Provide + private func makeAuthService() -> AuthService { + AuthServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/DevelopmentGoalServiceGraph.swift b/Application/Infra/Sources/Graph/DevelopmentGoalServiceGraph.swift new file mode 100644 index 00000000..1dc8902d --- /dev/null +++ b/Application/Infra/Sources/Graph/DevelopmentGoalServiceGraph.swift @@ -0,0 +1,19 @@ +// +// DevelopmentGoalServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class DevelopmentGoalServiceGraph { + public init() { } + + @Provide + private func makeDevelopmentGoalService() -> DevelopmentGoalService { + DevelopmentGoalServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/DevelopmentRecordServiceGraph.swift b/Application/Infra/Sources/Graph/DevelopmentRecordServiceGraph.swift new file mode 100644 index 00000000..84f8e138 --- /dev/null +++ b/Application/Infra/Sources/Graph/DevelopmentRecordServiceGraph.swift @@ -0,0 +1,19 @@ +// +// DevelopmentRecordServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class DevelopmentRecordServiceGraph { + public init() { } + + @Provide + private func makeDevelopmentRecordService() -> DevelopmentRecordService { + DevelopmentRecordServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/FirebaseAppServiceGraph.swift b/Application/Infra/Sources/Graph/FirebaseAppServiceGraph.swift new file mode 100644 index 00000000..2f8a7804 --- /dev/null +++ b/Application/Infra/Sources/Graph/FirebaseAppServiceGraph.swift @@ -0,0 +1,19 @@ +// +// FirebaseAppServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class FirebaseAppServiceGraph { + public init() { } + + @Provide + private func makeFirebaseAppService() -> FirebaseAppService { + FirebaseAppServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/GithubAuthenticationServiceGraph.swift b/Application/Infra/Sources/Graph/GithubAuthenticationServiceGraph.swift new file mode 100644 index 00000000..a25b2980 --- /dev/null +++ b/Application/Infra/Sources/Graph/GithubAuthenticationServiceGraph.swift @@ -0,0 +1,19 @@ +// +// GithubAuthenticationServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class GithubAuthenticationServiceGraph { + public init() { } + + @Provide + private func makeGithubAuthenticationService() -> GithubAuthenticationService { + GithubAuthenticationServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/GoogleAuthenticationServiceGraph.swift b/Application/Infra/Sources/Graph/GoogleAuthenticationServiceGraph.swift new file mode 100644 index 00000000..b78c6d0d --- /dev/null +++ b/Application/Infra/Sources/Graph/GoogleAuthenticationServiceGraph.swift @@ -0,0 +1,19 @@ +// +// GoogleAuthenticationServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class GoogleAuthenticationServiceGraph { + public init() { } + + @Provide + private func makeGoogleAuthenticationService() -> GoogleAuthenticationService { + GoogleAuthenticationServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/NWPathConnectivityProviderGraph.swift b/Application/Infra/Sources/Graph/NWPathConnectivityProviderGraph.swift new file mode 100644 index 00000000..d8c591ef --- /dev/null +++ b/Application/Infra/Sources/Graph/NWPathConnectivityProviderGraph.swift @@ -0,0 +1,19 @@ +// +// NWPathConnectivityProviderGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class NWPathConnectivityProviderGraph { + public init() { } + + @Provide(.lazy) + private func makeNWPathConnectivityProvider() -> NWPathConnectivityProvider { + NWPathConnectivityProviderImpl() + } +} diff --git a/Application/Infra/Sources/Graph/ProfileImageDataServiceGraph.swift b/Application/Infra/Sources/Graph/ProfileImageDataServiceGraph.swift new file mode 100644 index 00000000..85d1f19e --- /dev/null +++ b/Application/Infra/Sources/Graph/ProfileImageDataServiceGraph.swift @@ -0,0 +1,19 @@ +// +// ProfileImageDataServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class ProfileImageDataServiceGraph { + public init() { } + + @Provide + private func makeProfileImageDataService() -> ProfileImageDataService { + ProfileImageDataServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/PushMessagingServiceGraph.swift b/Application/Infra/Sources/Graph/PushMessagingServiceGraph.swift new file mode 100644 index 00000000..9804af9e --- /dev/null +++ b/Application/Infra/Sources/Graph/PushMessagingServiceGraph.swift @@ -0,0 +1,19 @@ +// +// PushMessagingServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class PushMessagingServiceGraph { + public init() { } + + @Provide + private func makePushMessagingService() -> PushMessagingService { + PushMessagingServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/PushNotificationServiceGraph.swift b/Application/Infra/Sources/Graph/PushNotificationServiceGraph.swift new file mode 100644 index 00000000..2cd110e0 --- /dev/null +++ b/Application/Infra/Sources/Graph/PushNotificationServiceGraph.swift @@ -0,0 +1,19 @@ +// +// PushNotificationServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class PushNotificationServiceGraph { + public init() { } + + @Provide + private func makePushNotificationService() -> PushNotificationService { + PushNotificationServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/TodoCategoryServiceGraph.swift b/Application/Infra/Sources/Graph/TodoCategoryServiceGraph.swift new file mode 100644 index 00000000..8b792f06 --- /dev/null +++ b/Application/Infra/Sources/Graph/TodoCategoryServiceGraph.swift @@ -0,0 +1,19 @@ +// +// TodoCategoryServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class TodoCategoryServiceGraph { + public init() { } + + @Provide + private func makeTodoCategoryService() -> TodoCategoryService { + TodoCategoryServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/TodoCommandServiceGraph.swift b/Application/Infra/Sources/Graph/TodoCommandServiceGraph.swift new file mode 100644 index 00000000..1edd6823 --- /dev/null +++ b/Application/Infra/Sources/Graph/TodoCommandServiceGraph.swift @@ -0,0 +1,19 @@ +// +// TodoCommandServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class TodoCommandServiceGraph { + public init() { } + + @Provide + private func makeTodoCommandService() -> TodoCommandService { + TodoCommandServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/TodoQueryServiceGraph.swift b/Application/Infra/Sources/Graph/TodoQueryServiceGraph.swift new file mode 100644 index 00000000..b0bd1021 --- /dev/null +++ b/Application/Infra/Sources/Graph/TodoQueryServiceGraph.swift @@ -0,0 +1,19 @@ +// +// TodoQueryServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class TodoQueryServiceGraph { + public init() { } + + @Provide + private func makeTodoQueryService() -> TodoQueryService { + TodoQueryServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/UserServiceGraph.swift b/Application/Infra/Sources/Graph/UserServiceGraph.swift new file mode 100644 index 00000000..925b009c --- /dev/null +++ b/Application/Infra/Sources/Graph/UserServiceGraph.swift @@ -0,0 +1,19 @@ +// +// UserServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class UserServiceGraph { + public init() { } + + @Provide + private func makeUserService() -> UserService { + UserServiceImpl() + } +} diff --git a/Application/Infra/Sources/Graph/WebPageMetadataServiceGraph.swift b/Application/Infra/Sources/Graph/WebPageMetadataServiceGraph.swift new file mode 100644 index 00000000..eb7f008b --- /dev/null +++ b/Application/Infra/Sources/Graph/WebPageMetadataServiceGraph.swift @@ -0,0 +1,25 @@ +// +// WebPageMetadataServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +public struct WebPageMetadataServiceGraphInput { + public let webPageImageStore: WebPageImageStore + + public init(webPageImageStore: WebPageImageStore) { + self.webPageImageStore = webPageImageStore + } +} + +@DependencyGraph(input: WebPageMetadataServiceGraphInput.self) +public final class WebPageMetadataServiceGraph { + @Provide + private func makeWebPageMetadataService() -> WebPageMetadataService { + WebPageMetadataServiceImpl(store: input.webPageImageStore) + } +} diff --git a/Application/Infra/Sources/Graph/WebPageServiceGraph.swift b/Application/Infra/Sources/Graph/WebPageServiceGraph.swift new file mode 100644 index 00000000..840e2ffb --- /dev/null +++ b/Application/Infra/Sources/Graph/WebPageServiceGraph.swift @@ -0,0 +1,19 @@ +// +// WebPageServiceGraph.swift +// Infra +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class WebPageServiceGraph { + public init() { } + + @Provide + private func makeWebPageService() -> WebPageService { + WebPageServiceImpl() + } +} From 79816eac9f13ab4c3cfa299ff7ee19abc4eaec68 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 13:52:11 +0900 Subject: [PATCH 04/19] =?UTF-8?q?refactor:=20Persistence=20provider=20grap?= =?UTF-8?q?h=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application/Persistence/Project.swift | 1 + .../Sources/Graph/MemoryCacheStoreGraph.swift | 19 +++++++++++++++++++ .../Sources/Graph/ThemeStoreGraph.swift | 19 +++++++++++++++++++ .../Graph/UserDefaultsStoreGraph.swift | 19 +++++++++++++++++++ .../Graph/WebPageImageStoreGraph.swift | 19 +++++++++++++++++++ 5 files changed, 77 insertions(+) create mode 100644 Application/Persistence/Sources/Graph/MemoryCacheStoreGraph.swift create mode 100644 Application/Persistence/Sources/Graph/ThemeStoreGraph.swift create mode 100644 Application/Persistence/Sources/Graph/UserDefaultsStoreGraph.swift create mode 100644 Application/Persistence/Sources/Graph/WebPageImageStoreGraph.swift diff --git a/Application/Persistence/Project.swift b/Application/Persistence/Project.swift index f127ad70..cd981a0f 100644 --- a/Application/Persistence/Project.swift +++ b/Application/Persistence/Project.swift @@ -11,6 +11,7 @@ let project = Project.devlogFramework( dependencies: [ .project(target: "Data", path: "../Data"), .project(target: "Core", path: "../Core"), + .project(target: "ThirdParty", path: "../../Libraries/ThirdParty"), ], hasTests: true ) diff --git a/Application/Persistence/Sources/Graph/MemoryCacheStoreGraph.swift b/Application/Persistence/Sources/Graph/MemoryCacheStoreGraph.swift new file mode 100644 index 00000000..53df7bdc --- /dev/null +++ b/Application/Persistence/Sources/Graph/MemoryCacheStoreGraph.swift @@ -0,0 +1,19 @@ +// +// MemoryCacheStoreGraph.swift +// Persistence +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class MemoryCacheStoreGraph { + public init() { } + + @Provide + private func makeMemoryCacheStore() -> MemoryCacheStore { + MemoryCacheStoreImpl() + } +} diff --git a/Application/Persistence/Sources/Graph/ThemeStoreGraph.swift b/Application/Persistence/Sources/Graph/ThemeStoreGraph.swift new file mode 100644 index 00000000..52bca27e --- /dev/null +++ b/Application/Persistence/Sources/Graph/ThemeStoreGraph.swift @@ -0,0 +1,19 @@ +// +// ThemeStoreGraph.swift +// Persistence +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class ThemeStoreGraph { + public init() { } + + @Provide + private func makeThemeStore() -> ThemeStore { + ThemeStoreImpl() + } +} diff --git a/Application/Persistence/Sources/Graph/UserDefaultsStoreGraph.swift b/Application/Persistence/Sources/Graph/UserDefaultsStoreGraph.swift new file mode 100644 index 00000000..7aedbc74 --- /dev/null +++ b/Application/Persistence/Sources/Graph/UserDefaultsStoreGraph.swift @@ -0,0 +1,19 @@ +// +// UserDefaultsStoreGraph.swift +// Persistence +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class UserDefaultsStoreGraph { + public init() { } + + @Provide + private func makeUserDefaultsStore() -> UserDefaultsStore { + UserDefaultsStoreImpl() + } +} diff --git a/Application/Persistence/Sources/Graph/WebPageImageStoreGraph.swift b/Application/Persistence/Sources/Graph/WebPageImageStoreGraph.swift new file mode 100644 index 00000000..2d3f3f0a --- /dev/null +++ b/Application/Persistence/Sources/Graph/WebPageImageStoreGraph.swift @@ -0,0 +1,19 @@ +// +// WebPageImageStoreGraph.swift +// Persistence +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class WebPageImageStoreGraph { + public init() { } + + @Provide + private func makeWebPageImageStore() -> WebPageImageStore { + WebPageImageStoreImpl() + } +} From fc784984a6fc45ad37afc9b25e033ae1e4f587e2 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 14:12:48 +0900 Subject: [PATCH 05/19] =?UTF-8?q?refactor:=20Persistence=20GraphSet=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/App/Graph/PersistenceGraphSet.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Application/App/Sources/App/Graph/PersistenceGraphSet.swift diff --git a/Application/App/Sources/App/Graph/PersistenceGraphSet.swift b/Application/App/Sources/App/Graph/PersistenceGraphSet.swift new file mode 100644 index 00000000..435000a6 --- /dev/null +++ b/Application/App/Sources/App/Graph/PersistenceGraphSet.swift @@ -0,0 +1,15 @@ +// +// PersistenceGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Persistence + +final class PersistenceGraphSet { + let userDefaultsStoreGraph = UserDefaultsStoreGraph() + let memoryCacheStoreGraph = MemoryCacheStoreGraph() + let themeStoreGraph = ThemeStoreGraph() + let webPageImageStoreGraph = WebPageImageStoreGraph() +} From d552954bb9d232557712db9c366261462cbf1e5a Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 14:13:30 +0900 Subject: [PATCH 06/19] =?UTF-8?q?refactor:=20Infra=20GraphSet=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../App/Sources/App/Graph/InfraGraphSet.swift | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Application/App/Sources/App/Graph/InfraGraphSet.swift diff --git a/Application/App/Sources/App/Graph/InfraGraphSet.swift b/Application/App/Sources/App/Graph/InfraGraphSet.swift new file mode 100644 index 00000000..8ac2a034 --- /dev/null +++ b/Application/App/Sources/App/Graph/InfraGraphSet.swift @@ -0,0 +1,43 @@ +// +// InfraGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Infra + +final class InfraGraphSet { + let firebaseAppServiceGraph = { + let graph = FirebaseAppServiceGraph() + graph.firebaseAppService.configure() + return graph + }() + let appStoreVersionServiceGraph = AppStoreVersionServiceGraph() + let analyticsServiceGraph = AnalyticsServiceGraph() + let pushMessagingServiceGraph = PushMessagingServiceGraph() + let appleAuthenticationServiceGraph = AppleAuthenticationServiceGraph() + let githubAuthenticationServiceGraph = GithubAuthenticationServiceGraph() + let googleAuthenticationServiceGraph = GoogleAuthenticationServiceGraph() + let authServiceGraph = AuthServiceGraph() + let todoQueryServiceGraph = TodoQueryServiceGraph() + let todoCommandServiceGraph = TodoCommandServiceGraph() + let developmentGoalServiceGraph = DevelopmentGoalServiceGraph() + let developmentRecordServiceGraph = DevelopmentRecordServiceGraph() + let todoCategoryServiceGraph = TodoCategoryServiceGraph() + let userServiceGraph = UserServiceGraph() + let profileImageDataServiceGraph = ProfileImageDataServiceGraph() + let pushNotificationServiceGraph = PushNotificationServiceGraph() + let webPageServiceGraph = WebPageServiceGraph() + let webPageMetadataServiceGraph: WebPageMetadataServiceGraph + let networkConnectivityProviderGraph = NWPathConnectivityProviderGraph() + + init(webPageImageStore: WebPageImageStore) { + self.webPageMetadataServiceGraph = WebPageMetadataServiceGraph( + input: WebPageMetadataServiceGraphInput( + webPageImageStore: webPageImageStore + ) + ) + } +} From 5b764b289605c20902138e395cdc85b4931a06fe Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 14:25:44 +0900 Subject: [PATCH 07/19] =?UTF-8?q?refactor:=20Data=20Repository=20provider?= =?UTF-8?q?=20graph=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application/Data/Project.swift | 1 + .../Graph/AnalyticsRepositoryGraph.swift | 25 ++++++++++ .../Graph/AppVersionRepositoryGraph.swift | 25 ++++++++++ .../Graph/AuthDataRepositoryGraph.swift | 41 ++++++++++++++++ .../Graph/AuthSessionRepositoryGraph.swift | 41 ++++++++++++++++ .../Graph/AuthenticationRepositoryGraph.swift | 49 +++++++++++++++++++ .../DevelopmentGoalRepositoryGraph.swift | 25 ++++++++++ .../DevelopmentRecordRepositoryGraph.swift | 25 ++++++++++ .../NetworkConnectivityRepositoryGraph.swift | 27 ++++++++++ .../ProfileImageDataRepositoryGraph.swift | 33 +++++++++++++ .../PushNotificationRepositoryGraph.swift | 37 ++++++++++++++ .../Graph/TodoCategoryRepositoryGraph.swift | 33 +++++++++++++ .../Graph/TodoMutationEventBusGraph.swift | 19 +++++++ .../Sources/Graph/TodoRepositoryGraph.swift | 49 +++++++++++++++++++ .../Graph/UserDataRepositoryGraph.swift | 25 ++++++++++ .../UserPreferencesRepositoryGraph.swift | 41 ++++++++++++++++ .../Graph/WebPageImageRepositoryGraph.swift | 33 +++++++++++++ .../Graph/WebPageRepositoryGraph.swift | 37 ++++++++++++++ .../WidgetTodoSnapshotRepositoryGraph.swift | 25 ++++++++++ 19 files changed, 591 insertions(+) create mode 100644 Application/Data/Sources/Graph/AnalyticsRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/AppVersionRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/AuthDataRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/AuthSessionRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/AuthenticationRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/DevelopmentGoalRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/DevelopmentRecordRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/NetworkConnectivityRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/ProfileImageDataRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/PushNotificationRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/TodoCategoryRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/TodoMutationEventBusGraph.swift create mode 100644 Application/Data/Sources/Graph/TodoRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/UserDataRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/UserPreferencesRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/WebPageImageRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/WebPageRepositoryGraph.swift create mode 100644 Application/Data/Sources/Graph/WidgetTodoSnapshotRepositoryGraph.swift diff --git a/Application/Data/Project.swift b/Application/Data/Project.swift index 750ea655..0e76019c 100644 --- a/Application/Data/Project.swift +++ b/Application/Data/Project.swift @@ -11,6 +11,7 @@ let project = Project.devlogFramework( dependencies: [ .project(target: "Domain", path: "../Domain"), .project(target: "Core", path: "../Core"), + .project(target: "ThirdParty", path: "../../Libraries/ThirdParty"), ], hasTests: true ) diff --git a/Application/Data/Sources/Graph/AnalyticsRepositoryGraph.swift b/Application/Data/Sources/Graph/AnalyticsRepositoryGraph.swift new file mode 100644 index 00000000..9bc9e603 --- /dev/null +++ b/Application/Data/Sources/Graph/AnalyticsRepositoryGraph.swift @@ -0,0 +1,25 @@ +// +// AnalyticsRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct AnalyticsRepositoryGraphInput { + public let analyticsService: AnalyticsService + + public init(analyticsService: AnalyticsService) { + self.analyticsService = analyticsService + } +} + +@DependencyGraph(input: AnalyticsRepositoryGraphInput.self) +public final class AnalyticsRepositoryGraph { + @Provide + private func makeAnalyticsRepository() -> AnalyticsRepository { + AnalyticsRepositoryImpl(analyticsService: input.analyticsService) + } +} diff --git a/Application/Data/Sources/Graph/AppVersionRepositoryGraph.swift b/Application/Data/Sources/Graph/AppVersionRepositoryGraph.swift new file mode 100644 index 00000000..2860f97c --- /dev/null +++ b/Application/Data/Sources/Graph/AppVersionRepositoryGraph.swift @@ -0,0 +1,25 @@ +// +// AppVersionRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct AppVersionRepositoryGraphInput { + public let service: AppStoreVersionService + + public init(service: AppStoreVersionService) { + self.service = service + } +} + +@DependencyGraph(input: AppVersionRepositoryGraphInput.self) +public final class AppVersionRepositoryGraph { + @Provide + private func makeAppVersionRepository() -> AppVersionRepository { + AppVersionRepositoryImpl(service: input.service) + } +} diff --git a/Application/Data/Sources/Graph/AuthDataRepositoryGraph.swift b/Application/Data/Sources/Graph/AuthDataRepositoryGraph.swift new file mode 100644 index 00000000..3f085e32 --- /dev/null +++ b/Application/Data/Sources/Graph/AuthDataRepositoryGraph.swift @@ -0,0 +1,41 @@ +// +// AuthDataRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct AuthDataRepositoryGraphInput { + public let authService: AuthService + public let appleAuthService: AppleAuthenticationService + public let githubAuthService: GithubAuthenticationService + public let googleAuthService: GoogleAuthenticationService + + public init( + authService: AuthService, + appleAuthService: AppleAuthenticationService, + githubAuthService: GithubAuthenticationService, + googleAuthService: GoogleAuthenticationService + ) { + self.authService = authService + self.appleAuthService = appleAuthService + self.githubAuthService = githubAuthService + self.googleAuthService = googleAuthService + } +} + +@DependencyGraph(input: AuthDataRepositoryGraphInput.self) +public final class AuthDataRepositoryGraph { + @Provide + private func makeAuthDataRepository() -> AuthDataRepository { + AuthDataRepositoryImpl( + authService: input.authService, + appleAuthService: input.appleAuthService, + githubAuthService: input.githubAuthService, + googleAuthService: input.googleAuthService + ) + } +} diff --git a/Application/Data/Sources/Graph/AuthSessionRepositoryGraph.swift b/Application/Data/Sources/Graph/AuthSessionRepositoryGraph.swift new file mode 100644 index 00000000..bd5aa02d --- /dev/null +++ b/Application/Data/Sources/Graph/AuthSessionRepositoryGraph.swift @@ -0,0 +1,41 @@ +// +// AuthSessionRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct AuthSessionRepositoryGraphInput { + public let authService: AuthService + public let todoCategoryService: TodoCategoryService + public let store: MemoryCacheStore + public let provider: AuthSessionStateProvider + + public init( + authService: AuthService, + todoCategoryService: TodoCategoryService, + store: MemoryCacheStore, + provider: AuthSessionStateProvider + ) { + self.authService = authService + self.todoCategoryService = todoCategoryService + self.store = store + self.provider = provider + } +} + +@DependencyGraph(input: AuthSessionRepositoryGraphInput.self) +public final class AuthSessionRepositoryGraph { + @Provide(.lazy) + private func makeAuthSessionRepository() -> AuthSessionRepository { + AuthSessionRepositoryImpl( + authService: input.authService, + todoCategoryService: input.todoCategoryService, + store: input.store, + provider: input.provider + ) + } +} diff --git a/Application/Data/Sources/Graph/AuthenticationRepositoryGraph.swift b/Application/Data/Sources/Graph/AuthenticationRepositoryGraph.swift new file mode 100644 index 00000000..c34ff2e1 --- /dev/null +++ b/Application/Data/Sources/Graph/AuthenticationRepositoryGraph.swift @@ -0,0 +1,49 @@ +// +// AuthenticationRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct AuthenticationRepositoryGraphInput { + public let authService: AuthService + public let appleAuthService: AppleAuthenticationService + public let githubAuthService: GithubAuthenticationService + public let googleAuthService: GoogleAuthenticationService + public let userService: UserService + public let widgetSnapshotUpdater: WidgetSnapshotUpdater + + public init( + authService: AuthService, + appleAuthService: AppleAuthenticationService, + githubAuthService: GithubAuthenticationService, + googleAuthService: GoogleAuthenticationService, + userService: UserService, + widgetSnapshotUpdater: WidgetSnapshotUpdater + ) { + self.authService = authService + self.appleAuthService = appleAuthService + self.githubAuthService = githubAuthService + self.googleAuthService = googleAuthService + self.userService = userService + self.widgetSnapshotUpdater = widgetSnapshotUpdater + } +} + +@DependencyGraph(input: AuthenticationRepositoryGraphInput.self) +public final class AuthenticationRepositoryGraph { + @Provide + private func makeAuthenticationRepository() -> AuthenticationRepository { + AuthenticationRepositoryImpl( + authService: input.authService, + appleAuthService: input.appleAuthService, + githubAuthService: input.githubAuthService, + googleAuthService: input.googleAuthService, + userService: input.userService, + widgetSnapshotUpdater: input.widgetSnapshotUpdater + ) + } +} diff --git a/Application/Data/Sources/Graph/DevelopmentGoalRepositoryGraph.swift b/Application/Data/Sources/Graph/DevelopmentGoalRepositoryGraph.swift new file mode 100644 index 00000000..b6ffaa7c --- /dev/null +++ b/Application/Data/Sources/Graph/DevelopmentGoalRepositoryGraph.swift @@ -0,0 +1,25 @@ +// +// DevelopmentGoalRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct DevelopmentGoalRepositoryGraphInput { + public let service: DevelopmentGoalService + + public init(service: DevelopmentGoalService) { + self.service = service + } +} + +@DependencyGraph(input: DevelopmentGoalRepositoryGraphInput.self) +public final class DevelopmentGoalRepositoryGraph { + @Provide + private func makeDevelopmentGoalRepository() -> DevelopmentGoalRepository { + DevelopmentGoalRepositoryImpl(service: input.service) + } +} diff --git a/Application/Data/Sources/Graph/DevelopmentRecordRepositoryGraph.swift b/Application/Data/Sources/Graph/DevelopmentRecordRepositoryGraph.swift new file mode 100644 index 00000000..f17ed1f9 --- /dev/null +++ b/Application/Data/Sources/Graph/DevelopmentRecordRepositoryGraph.swift @@ -0,0 +1,25 @@ +// +// DevelopmentRecordRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct DevelopmentRecordRepositoryGraphInput { + public let service: DevelopmentRecordService + + public init(service: DevelopmentRecordService) { + self.service = service + } +} + +@DependencyGraph(input: DevelopmentRecordRepositoryGraphInput.self) +public final class DevelopmentRecordRepositoryGraph { + @Provide + private func makeDevelopmentRecordRepository() -> DevelopmentRecordRepository { + DevelopmentRecordRepositoryImpl(service: input.service) + } +} diff --git a/Application/Data/Sources/Graph/NetworkConnectivityRepositoryGraph.swift b/Application/Data/Sources/Graph/NetworkConnectivityRepositoryGraph.swift new file mode 100644 index 00000000..ae5f1609 --- /dev/null +++ b/Application/Data/Sources/Graph/NetworkConnectivityRepositoryGraph.swift @@ -0,0 +1,27 @@ +// +// NetworkConnectivityRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct NetworkConnectivityRepositoryGraphInput { + public let connectivityProvider: NWPathConnectivityProvider + + public init(connectivityProvider: NWPathConnectivityProvider) { + self.connectivityProvider = connectivityProvider + } +} + +@DependencyGraph(input: NetworkConnectivityRepositoryGraphInput.self) +public final class NetworkConnectivityRepositoryGraph { + @Provide(.lazy) + private func makeNetworkConnectivityRepository() -> NetworkConnectivityRepository { + NetworkConnectivityRepositoryImpl( + connectivityProvider: input.connectivityProvider + ) + } +} diff --git a/Application/Data/Sources/Graph/ProfileImageDataRepositoryGraph.swift b/Application/Data/Sources/Graph/ProfileImageDataRepositoryGraph.swift new file mode 100644 index 00000000..6697e84e --- /dev/null +++ b/Application/Data/Sources/Graph/ProfileImageDataRepositoryGraph.swift @@ -0,0 +1,33 @@ +// +// ProfileImageDataRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct ProfileImageDataRepositoryGraphInput { + public let service: ProfileImageDataService + public let store: MemoryCacheStore + + public init( + service: ProfileImageDataService, + store: MemoryCacheStore + ) { + self.service = service + self.store = store + } +} + +@DependencyGraph(input: ProfileImageDataRepositoryGraphInput.self) +public final class ProfileImageDataRepositoryGraph { + @Provide + private func makeProfileImageDataRepository() -> ProfileImageDataRepository { + ProfileImageDataRepositoryImpl( + service: input.service, + store: input.store + ) + } +} diff --git a/Application/Data/Sources/Graph/PushNotificationRepositoryGraph.swift b/Application/Data/Sources/Graph/PushNotificationRepositoryGraph.swift new file mode 100644 index 00000000..1cad7f7b --- /dev/null +++ b/Application/Data/Sources/Graph/PushNotificationRepositoryGraph.swift @@ -0,0 +1,37 @@ +// +// PushNotificationRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct PushNotificationRepositoryGraphInput { + public let pushNotificationService: PushNotificationService + public let todoCategoryService: TodoCategoryService + public let store: MemoryCacheStore + + public init( + pushNotificationService: PushNotificationService, + todoCategoryService: TodoCategoryService, + store: MemoryCacheStore + ) { + self.pushNotificationService = pushNotificationService + self.todoCategoryService = todoCategoryService + self.store = store + } +} + +@DependencyGraph(input: PushNotificationRepositoryGraphInput.self) +public final class PushNotificationRepositoryGraph { + @Provide + private func makePushNotificationRepository() -> PushNotificationRepository { + PushNotificationRepositoryImpl( + pushNotificationService: input.pushNotificationService, + todoCategoryService: input.todoCategoryService, + store: input.store + ) + } +} diff --git a/Application/Data/Sources/Graph/TodoCategoryRepositoryGraph.swift b/Application/Data/Sources/Graph/TodoCategoryRepositoryGraph.swift new file mode 100644 index 00000000..272af4f4 --- /dev/null +++ b/Application/Data/Sources/Graph/TodoCategoryRepositoryGraph.swift @@ -0,0 +1,33 @@ +// +// TodoCategoryRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct TodoCategoryRepositoryGraphInput { + public let todoCategoryService: TodoCategoryService + public let store: MemoryCacheStore + + public init( + todoCategoryService: TodoCategoryService, + store: MemoryCacheStore + ) { + self.todoCategoryService = todoCategoryService + self.store = store + } +} + +@DependencyGraph(input: TodoCategoryRepositoryGraphInput.self) +public final class TodoCategoryRepositoryGraph { + @Provide + private func makeTodoCategoryRepository() -> TodoCategoryRepository { + TodoCategoryRepositoryImpl( + todoCategoryService: input.todoCategoryService, + store: input.store + ) + } +} diff --git a/Application/Data/Sources/Graph/TodoMutationEventBusGraph.swift b/Application/Data/Sources/Graph/TodoMutationEventBusGraph.swift new file mode 100644 index 00000000..c69b3abf --- /dev/null +++ b/Application/Data/Sources/Graph/TodoMutationEventBusGraph.swift @@ -0,0 +1,19 @@ +// +// TodoMutationEventBusGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +@DependencyGraph +public final class TodoMutationEventBusGraph { + public init() { } + + @Provide + private func makeTodoMutationEventBus() -> TodoMutationEventBus { + TodoMutationEventBusImpl() + } +} diff --git a/Application/Data/Sources/Graph/TodoRepositoryGraph.swift b/Application/Data/Sources/Graph/TodoRepositoryGraph.swift new file mode 100644 index 00000000..703b2eb3 --- /dev/null +++ b/Application/Data/Sources/Graph/TodoRepositoryGraph.swift @@ -0,0 +1,49 @@ +// +// TodoRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct TodoRepositoryGraphInput { + public let queryService: TodoQueryService + public let commandService: TodoCommandService + public let todoCategoryService: TodoCategoryService + public let store: MemoryCacheStore + public let updater: WidgetSnapshotUpdater + public let eventBus: TodoMutationEventBus + + public init( + queryService: TodoQueryService, + commandService: TodoCommandService, + todoCategoryService: TodoCategoryService, + store: MemoryCacheStore, + updater: WidgetSnapshotUpdater, + eventBus: TodoMutationEventBus + ) { + self.queryService = queryService + self.commandService = commandService + self.todoCategoryService = todoCategoryService + self.store = store + self.updater = updater + self.eventBus = eventBus + } +} + +@DependencyGraph(input: TodoRepositoryGraphInput.self) +public final class TodoRepositoryGraph { + @Provide + private func makeTodoRepository() -> TodoRepository { + TodoRepositoryImpl( + queryService: input.queryService, + commandService: input.commandService, + todoCategoryService: input.todoCategoryService, + store: input.store, + updater: input.updater, + eventBus: input.eventBus + ) + } +} diff --git a/Application/Data/Sources/Graph/UserDataRepositoryGraph.swift b/Application/Data/Sources/Graph/UserDataRepositoryGraph.swift new file mode 100644 index 00000000..aedd81ae --- /dev/null +++ b/Application/Data/Sources/Graph/UserDataRepositoryGraph.swift @@ -0,0 +1,25 @@ +// +// UserDataRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct UserDataRepositoryGraphInput { + public let userService: UserService + + public init(userService: UserService) { + self.userService = userService + } +} + +@DependencyGraph(input: UserDataRepositoryGraphInput.self) +public final class UserDataRepositoryGraph { + @Provide + private func makeUserDataRepository() -> UserDataRepository { + UserDataRepositoryImpl(userService: input.userService) + } +} diff --git a/Application/Data/Sources/Graph/UserPreferencesRepositoryGraph.swift b/Application/Data/Sources/Graph/UserPreferencesRepositoryGraph.swift new file mode 100644 index 00000000..ddb97c39 --- /dev/null +++ b/Application/Data/Sources/Graph/UserPreferencesRepositoryGraph.swift @@ -0,0 +1,41 @@ +// +// UserPreferencesRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct UserPreferencesRepositoryGraphInput { + public let store: UserDefaultsStore + public let themeStore: ThemeStore + public let widgetSnapshotPreferenceStore: WidgetSnapshotPreferenceStore + public let widgetSyncEventBus: WidgetSyncEventBus + + public init( + store: UserDefaultsStore, + themeStore: ThemeStore, + widgetSnapshotPreferenceStore: WidgetSnapshotPreferenceStore, + widgetSyncEventBus: WidgetSyncEventBus + ) { + self.store = store + self.themeStore = themeStore + self.widgetSnapshotPreferenceStore = widgetSnapshotPreferenceStore + self.widgetSyncEventBus = widgetSyncEventBus + } +} + +@DependencyGraph(input: UserPreferencesRepositoryGraphInput.self) +public final class UserPreferencesRepositoryGraph { + @Provide + private func makeUserPreferencesRepository() -> UserPreferencesRepository { + UserPreferencesRepositoryImpl( + store: input.store, + themeStore: input.themeStore, + widgetSnapshotPreferenceStore: input.widgetSnapshotPreferenceStore, + widgetSyncEventBus: input.widgetSyncEventBus + ) + } +} diff --git a/Application/Data/Sources/Graph/WebPageImageRepositoryGraph.swift b/Application/Data/Sources/Graph/WebPageImageRepositoryGraph.swift new file mode 100644 index 00000000..016ada06 --- /dev/null +++ b/Application/Data/Sources/Graph/WebPageImageRepositoryGraph.swift @@ -0,0 +1,33 @@ +// +// WebPageImageRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct WebPageImageRepositoryGraphInput { + public let authService: AuthService + public let store: WebPageImageStore + + public init( + authService: AuthService, + store: WebPageImageStore + ) { + self.authService = authService + self.store = store + } +} + +@DependencyGraph(input: WebPageImageRepositoryGraphInput.self) +public final class WebPageImageRepositoryGraph { + @Provide + private func makeWebPageImageRepository() -> WebPageImageRepository { + WebPageImageRepositoryImpl( + authService: input.authService, + store: input.store + ) + } +} diff --git a/Application/Data/Sources/Graph/WebPageRepositoryGraph.swift b/Application/Data/Sources/Graph/WebPageRepositoryGraph.swift new file mode 100644 index 00000000..13b599fb --- /dev/null +++ b/Application/Data/Sources/Graph/WebPageRepositoryGraph.swift @@ -0,0 +1,37 @@ +// +// WebPageRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct WebPageRepositoryGraphInput { + public let authService: AuthService + public let metadataService: WebPageMetadataService + public let webPageService: WebPageService + + public init( + authService: AuthService, + metadataService: WebPageMetadataService, + webPageService: WebPageService + ) { + self.authService = authService + self.metadataService = metadataService + self.webPageService = webPageService + } +} + +@DependencyGraph(input: WebPageRepositoryGraphInput.self) +public final class WebPageRepositoryGraph { + @Provide + private func makeWebPageRepository() -> WebPageRepository { + WebPageRepositoryImpl( + authService: input.authService, + metadataService: input.metadataService, + webPageService: input.webPageService + ) + } +} diff --git a/Application/Data/Sources/Graph/WidgetTodoSnapshotRepositoryGraph.swift b/Application/Data/Sources/Graph/WidgetTodoSnapshotRepositoryGraph.swift new file mode 100644 index 00000000..07c0735a --- /dev/null +++ b/Application/Data/Sources/Graph/WidgetTodoSnapshotRepositoryGraph.swift @@ -0,0 +1,25 @@ +// +// WidgetTodoSnapshotRepositoryGraph.swift +// Data +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Domain + +public struct WidgetTodoSnapshotRepositoryGraphInput { + public let queryService: TodoQueryService + + public init(queryService: TodoQueryService) { + self.queryService = queryService + } +} + +@DependencyGraph(input: WidgetTodoSnapshotRepositoryGraphInput.self) +public final class WidgetTodoSnapshotRepositoryGraph { + @Provide + private func makeWidgetTodoSnapshotRepository() -> WidgetTodoSnapshotRepository { + WidgetTodoSnapshotRepositoryImpl(queryService: input.queryService) + } +} From cd4992912f594a7075fbfd941e67b02b3a885450 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 14:47:50 +0900 Subject: [PATCH 08/19] =?UTF-8?q?refactor:=20Widget=20provider=20graph=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application/Widget/Project.swift | 1 + .../Graph/AuthSessionStateProviderGraph.swift | 19 ++++++++++ .../Graph/WidgetSessionSyncHandlerGraph.swift | 33 +++++++++++++++++ .../WidgetSharedDefaultsStoreGraph.swift | 19 ++++++++++ .../WidgetSnapshotPreferenceStoreGraph.swift | 19 ++++++++++ .../Graph/WidgetSnapshotStoreGraph.swift | 25 +++++++++++++ .../Graph/WidgetSnapshotUpdaterGraph.swift | 34 +++++++++++++++++ .../Graph/WidgetSyncEventBusGraph.swift | 19 ++++++++++ .../Graph/WidgetSyncEventHandlerGraph.swift | 37 +++++++++++++++++++ 9 files changed, 206 insertions(+) create mode 100644 Application/Widget/Sources/Graph/AuthSessionStateProviderGraph.swift create mode 100644 Application/Widget/Sources/Graph/WidgetSessionSyncHandlerGraph.swift create mode 100644 Application/Widget/Sources/Graph/WidgetSharedDefaultsStoreGraph.swift create mode 100644 Application/Widget/Sources/Graph/WidgetSnapshotPreferenceStoreGraph.swift create mode 100644 Application/Widget/Sources/Graph/WidgetSnapshotStoreGraph.swift create mode 100644 Application/Widget/Sources/Graph/WidgetSnapshotUpdaterGraph.swift create mode 100644 Application/Widget/Sources/Graph/WidgetSyncEventBusGraph.swift create mode 100644 Application/Widget/Sources/Graph/WidgetSyncEventHandlerGraph.swift diff --git a/Application/Widget/Project.swift b/Application/Widget/Project.swift index 0a7ce72b..deaf05ab 100644 --- a/Application/Widget/Project.swift +++ b/Application/Widget/Project.swift @@ -12,6 +12,7 @@ let project = Project.devlogFramework( .project(target: "Data", path: "../Data"), .project(target: "Core", path: "../Core"), .project(target: "WidgetCore", path: "../../Widget/WidgetCore"), + .project(target: "ThirdParty", path: "../../Libraries/ThirdParty"), ], hasTests: true ) diff --git a/Application/Widget/Sources/Graph/AuthSessionStateProviderGraph.swift b/Application/Widget/Sources/Graph/AuthSessionStateProviderGraph.swift new file mode 100644 index 00000000..8e07d7a3 --- /dev/null +++ b/Application/Widget/Sources/Graph/AuthSessionStateProviderGraph.swift @@ -0,0 +1,19 @@ +// +// AuthSessionStateProviderGraph.swift +// Widget +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class AuthSessionStateProviderGraph { + public init() { } + + @Provide + private func makeAuthSessionStateProvider() -> AuthSessionStateProvider { + AuthSessionStateProviderImpl() + } +} diff --git a/Application/Widget/Sources/Graph/WidgetSessionSyncHandlerGraph.swift b/Application/Widget/Sources/Graph/WidgetSessionSyncHandlerGraph.swift new file mode 100644 index 00000000..ddd12c19 --- /dev/null +++ b/Application/Widget/Sources/Graph/WidgetSessionSyncHandlerGraph.swift @@ -0,0 +1,33 @@ +// +// WidgetSessionSyncHandlerGraph.swift +// Widget +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +public struct WidgetSessionSyncHandlerGraphInput { + public let provider: AuthSessionStateProvider + public let widgetSyncEventBus: WidgetSyncEventBus + + public init( + provider: AuthSessionStateProvider, + widgetSyncEventBus: WidgetSyncEventBus + ) { + self.provider = provider + self.widgetSyncEventBus = widgetSyncEventBus + } +} + +@DependencyGraph(input: WidgetSessionSyncHandlerGraphInput.self) +public final class WidgetSessionSyncHandlerGraph { + @Provide(.lazy) + private func makeWidgetSessionSyncHandler() -> WidgetSessionSyncHandler { + WidgetSessionSyncHandler( + provider: input.provider, + widgetSyncEventBus: input.widgetSyncEventBus + ) + } +} diff --git a/Application/Widget/Sources/Graph/WidgetSharedDefaultsStoreGraph.swift b/Application/Widget/Sources/Graph/WidgetSharedDefaultsStoreGraph.swift new file mode 100644 index 00000000..f0826e9e --- /dev/null +++ b/Application/Widget/Sources/Graph/WidgetSharedDefaultsStoreGraph.swift @@ -0,0 +1,19 @@ +// +// WidgetSharedDefaultsStoreGraph.swift +// Widget +// +// Created by opfic on 9/7/26. +// + +import Cradle +import WidgetCore + +@DependencyGraph +public final class WidgetSharedDefaultsStoreGraph { + public init() { } + + @Provide + private func makeWidgetSharedDefaultsStore() -> WidgetSharedDefaultsStore { + WidgetSharedDefaultsStore() + } +} diff --git a/Application/Widget/Sources/Graph/WidgetSnapshotPreferenceStoreGraph.swift b/Application/Widget/Sources/Graph/WidgetSnapshotPreferenceStoreGraph.swift new file mode 100644 index 00000000..65082b67 --- /dev/null +++ b/Application/Widget/Sources/Graph/WidgetSnapshotPreferenceStoreGraph.swift @@ -0,0 +1,19 @@ +// +// WidgetSnapshotPreferenceStoreGraph.swift +// Widget +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class WidgetSnapshotPreferenceStoreGraph { + public init() { } + + @Provide + private func makeWidgetSnapshotPreferenceStore() -> WidgetSnapshotPreferenceStore { + WidgetSnapshotPreferenceStoreImpl() + } +} diff --git a/Application/Widget/Sources/Graph/WidgetSnapshotStoreGraph.swift b/Application/Widget/Sources/Graph/WidgetSnapshotStoreGraph.swift new file mode 100644 index 00000000..1542a2ed --- /dev/null +++ b/Application/Widget/Sources/Graph/WidgetSnapshotStoreGraph.swift @@ -0,0 +1,25 @@ +// +// WidgetSnapshotStoreGraph.swift +// Widget +// +// Created by opfic on 9/7/26. +// + +import Cradle +import WidgetCore + +public struct WidgetSnapshotStoreGraphInput { + public let store: WidgetSharedDefaultsStore + + public init(store: WidgetSharedDefaultsStore) { + self.store = store + } +} + +@DependencyGraph(input: WidgetSnapshotStoreGraphInput.self) +public final class WidgetSnapshotStoreGraph { + @Provide + private func makeWidgetSnapshotStore() -> WidgetSnapshotStore { + WidgetSnapshotStore(store: input.store) + } +} diff --git a/Application/Widget/Sources/Graph/WidgetSnapshotUpdaterGraph.swift b/Application/Widget/Sources/Graph/WidgetSnapshotUpdaterGraph.swift new file mode 100644 index 00000000..989f1cef --- /dev/null +++ b/Application/Widget/Sources/Graph/WidgetSnapshotUpdaterGraph.swift @@ -0,0 +1,34 @@ +// +// WidgetSnapshotUpdaterGraph.swift +// Widget +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data +import WidgetCore + +public struct WidgetSnapshotUpdaterGraphInput { + public let snapshotStore: WidgetSnapshotStore + public let preferenceStore: WidgetSnapshotPreferenceStore + + public init( + snapshotStore: WidgetSnapshotStore, + preferenceStore: WidgetSnapshotPreferenceStore + ) { + self.snapshotStore = snapshotStore + self.preferenceStore = preferenceStore + } +} + +@DependencyGraph(input: WidgetSnapshotUpdaterGraphInput.self) +public final class WidgetSnapshotUpdaterGraph { + @Provide + private func makeWidgetSnapshotUpdater() -> WidgetSnapshotUpdater { + WidgetSnapshotUpdaterImpl( + snapshotStore: input.snapshotStore, + preferenceStore: input.preferenceStore + ) + } +} diff --git a/Application/Widget/Sources/Graph/WidgetSyncEventBusGraph.swift b/Application/Widget/Sources/Graph/WidgetSyncEventBusGraph.swift new file mode 100644 index 00000000..b4d97fa2 --- /dev/null +++ b/Application/Widget/Sources/Graph/WidgetSyncEventBusGraph.swift @@ -0,0 +1,19 @@ +// +// WidgetSyncEventBusGraph.swift +// Widget +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +@DependencyGraph +public final class WidgetSyncEventBusGraph { + public init() { } + + @Provide + private func makeWidgetSyncEventBus() -> WidgetSyncEventBus { + WidgetSyncEventBusImpl() + } +} diff --git a/Application/Widget/Sources/Graph/WidgetSyncEventHandlerGraph.swift b/Application/Widget/Sources/Graph/WidgetSyncEventHandlerGraph.swift new file mode 100644 index 00000000..c21cbb28 --- /dev/null +++ b/Application/Widget/Sources/Graph/WidgetSyncEventHandlerGraph.swift @@ -0,0 +1,37 @@ +// +// WidgetSyncEventHandlerGraph.swift +// Widget +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +public struct WidgetSyncEventHandlerGraphInput { + public let eventBus: WidgetSyncEventBus + public let repository: WidgetTodoSnapshotRepository + public let snapshotUpdater: WidgetSnapshotUpdater + + public init( + eventBus: WidgetSyncEventBus, + repository: WidgetTodoSnapshotRepository, + snapshotUpdater: WidgetSnapshotUpdater + ) { + self.eventBus = eventBus + self.repository = repository + self.snapshotUpdater = snapshotUpdater + } +} + +@DependencyGraph(input: WidgetSyncEventHandlerGraphInput.self) +public final class WidgetSyncEventHandlerGraph { + @Provide(.lazy) + private func makeWidgetSyncEventHandler() -> WidgetSyncEventHandler { + WidgetSyncEventHandler( + eventBus: input.eventBus, + repository: input.repository, + snapshotUpdater: input.snapshotUpdater + ) + } +} From 80a547cd8ca18bdcf07697fafa781dad19ee4016 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 14:48:17 +0900 Subject: [PATCH 09/19] =?UTF-8?q?refactor:=20Widget=20GraphSet=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/App/Graph/WidgetGraphSet.swift | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Application/App/Sources/App/Graph/WidgetGraphSet.swift diff --git a/Application/App/Sources/App/Graph/WidgetGraphSet.swift b/Application/App/Sources/App/Graph/WidgetGraphSet.swift new file mode 100644 index 00000000..c7b6d5b7 --- /dev/null +++ b/Application/App/Sources/App/Graph/WidgetGraphSet.swift @@ -0,0 +1,31 @@ +// +// WidgetGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Widget + +final class WidgetGraphSet { + let authSessionStateProviderGraph = AuthSessionStateProviderGraph() + let widgetSyncEventBusGraph = WidgetSyncEventBusGraph() + let widgetSharedDefaultsStoreGraph = WidgetSharedDefaultsStoreGraph() + let widgetSnapshotPreferenceStoreGraph = WidgetSnapshotPreferenceStoreGraph() + let widgetSnapshotStoreGraph: WidgetSnapshotStoreGraph + let widgetSnapshotUpdaterGraph: WidgetSnapshotUpdaterGraph + + init() { + self.widgetSnapshotStoreGraph = WidgetSnapshotStoreGraph( + input: WidgetSnapshotStoreGraphInput( + store: widgetSharedDefaultsStoreGraph.widgetSharedDefaultsStore + ) + ) + self.widgetSnapshotUpdaterGraph = WidgetSnapshotUpdaterGraph( + input: WidgetSnapshotUpdaterGraphInput( + snapshotStore: widgetSnapshotStoreGraph.widgetSnapshotStore, + preferenceStore: widgetSnapshotPreferenceStoreGraph.widgetSnapshotPreferenceStore + ) + ) + } +} From bcd91c2453e9e515278abee1dc95df0ec6ac2ce5 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 15:03:37 +0900 Subject: [PATCH 10/19] =?UTF-8?q?refactor:=20Data=20Repository=20GraphSet?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthenticationRepositoryGraphSet.swift | 43 +++++++++++++++++ .../Graph/DevelopmentRepositoryGraphSet.swift | 30 ++++++++++++ .../App/Graph/TodoRepositoryGraphSet.swift | 48 +++++++++++++++++++ .../App/Graph/WebPageRepositoryGraphSet.swift | 36 ++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 Application/App/Sources/App/Graph/AuthenticationRepositoryGraphSet.swift create mode 100644 Application/App/Sources/App/Graph/DevelopmentRepositoryGraphSet.swift create mode 100644 Application/App/Sources/App/Graph/TodoRepositoryGraphSet.swift create mode 100644 Application/App/Sources/App/Graph/WebPageRepositoryGraphSet.swift diff --git a/Application/App/Sources/App/Graph/AuthenticationRepositoryGraphSet.swift b/Application/App/Sources/App/Graph/AuthenticationRepositoryGraphSet.swift new file mode 100644 index 00000000..fb2144ef --- /dev/null +++ b/Application/App/Sources/App/Graph/AuthenticationRepositoryGraphSet.swift @@ -0,0 +1,43 @@ +// +// AuthenticationRepositoryGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Infra +import Widget + +final class AuthenticationRepositoryGraphSet { + let authenticationRepositoryGraph: AuthenticationRepositoryGraph + let authDataRepositoryGraph: AuthDataRepositoryGraph + + init( + authServiceGraph: AuthServiceGraph, + appleAuthenticationServiceGraph: AppleAuthenticationServiceGraph, + githubAuthenticationServiceGraph: GithubAuthenticationServiceGraph, + googleAuthenticationServiceGraph: GoogleAuthenticationServiceGraph, + userServiceGraph: UserServiceGraph, + widgetSnapshotUpdaterGraph: WidgetSnapshotUpdaterGraph + ) { + self.authenticationRepositoryGraph = AuthenticationRepositoryGraph( + input: AuthenticationRepositoryGraphInput( + authService: authServiceGraph.authService, + appleAuthService: appleAuthenticationServiceGraph.appleAuthenticationService, + githubAuthService: githubAuthenticationServiceGraph.githubAuthenticationService, + googleAuthService: googleAuthenticationServiceGraph.googleAuthenticationService, + userService: userServiceGraph.userService, + widgetSnapshotUpdater: widgetSnapshotUpdaterGraph.widgetSnapshotUpdater + ) + ) + self.authDataRepositoryGraph = AuthDataRepositoryGraph( + input: AuthDataRepositoryGraphInput( + authService: authServiceGraph.authService, + appleAuthService: appleAuthenticationServiceGraph.appleAuthenticationService, + githubAuthService: githubAuthenticationServiceGraph.githubAuthenticationService, + googleAuthService: googleAuthenticationServiceGraph.googleAuthenticationService + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/DevelopmentRepositoryGraphSet.swift b/Application/App/Sources/App/Graph/DevelopmentRepositoryGraphSet.swift new file mode 100644 index 00000000..40b4c0de --- /dev/null +++ b/Application/App/Sources/App/Graph/DevelopmentRepositoryGraphSet.swift @@ -0,0 +1,30 @@ +// +// DevelopmentRepositoryGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Infra + +final class DevelopmentRepositoryGraphSet { + let developmentGoalRepositoryGraph: DevelopmentGoalRepositoryGraph + let developmentRecordRepositoryGraph: DevelopmentRecordRepositoryGraph + + init( + developmentGoalServiceGraph: DevelopmentGoalServiceGraph, + developmentRecordServiceGraph: DevelopmentRecordServiceGraph + ) { + self.developmentGoalRepositoryGraph = DevelopmentGoalRepositoryGraph( + input: DevelopmentGoalRepositoryGraphInput( + service: developmentGoalServiceGraph.developmentGoalService + ) + ) + self.developmentRecordRepositoryGraph = DevelopmentRecordRepositoryGraph( + input: DevelopmentRecordRepositoryGraphInput( + service: developmentRecordServiceGraph.developmentRecordService + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/TodoRepositoryGraphSet.swift b/Application/App/Sources/App/Graph/TodoRepositoryGraphSet.swift new file mode 100644 index 00000000..6b6d45b1 --- /dev/null +++ b/Application/App/Sources/App/Graph/TodoRepositoryGraphSet.swift @@ -0,0 +1,48 @@ +// +// TodoRepositoryGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Infra +import Persistence +import Widget + +final class TodoRepositoryGraphSet { + let todoMutationEventBusGraph = TodoMutationEventBusGraph() + let todoRepositoryGraph: TodoRepositoryGraph + let todoCategoryRepositoryGraph: TodoCategoryRepositoryGraph + let widgetTodoSnapshotRepositoryGraph: WidgetTodoSnapshotRepositoryGraph + + init( + todoQueryServiceGraph: TodoQueryServiceGraph, + todoCommandServiceGraph: TodoCommandServiceGraph, + todoCategoryServiceGraph: TodoCategoryServiceGraph, + memoryCacheStoreGraph: MemoryCacheStoreGraph, + widgetSnapshotUpdaterGraph: WidgetSnapshotUpdaterGraph + ) { + self.todoRepositoryGraph = TodoRepositoryGraph( + input: TodoRepositoryGraphInput( + queryService: todoQueryServiceGraph.todoQueryService, + commandService: todoCommandServiceGraph.todoCommandService, + todoCategoryService: todoCategoryServiceGraph.todoCategoryService, + store: memoryCacheStoreGraph.memoryCacheStore, + updater: widgetSnapshotUpdaterGraph.widgetSnapshotUpdater, + eventBus: todoMutationEventBusGraph.todoMutationEventBus + ) + ) + self.todoCategoryRepositoryGraph = TodoCategoryRepositoryGraph( + input: TodoCategoryRepositoryGraphInput( + todoCategoryService: todoCategoryServiceGraph.todoCategoryService, + store: memoryCacheStoreGraph.memoryCacheStore + ) + ) + self.widgetTodoSnapshotRepositoryGraph = WidgetTodoSnapshotRepositoryGraph( + input: WidgetTodoSnapshotRepositoryGraphInput( + queryService: todoQueryServiceGraph.todoQueryService + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/WebPageRepositoryGraphSet.swift b/Application/App/Sources/App/Graph/WebPageRepositoryGraphSet.swift new file mode 100644 index 00000000..6e99f886 --- /dev/null +++ b/Application/App/Sources/App/Graph/WebPageRepositoryGraphSet.swift @@ -0,0 +1,36 @@ +// +// WebPageRepositoryGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Infra +import Persistence + +final class WebPageRepositoryGraphSet { + let webPageRepositoryGraph: WebPageRepositoryGraph + let webPageImageRepositoryGraph: WebPageImageRepositoryGraph + + init( + authServiceGraph: AuthServiceGraph, + webPageMetadataServiceGraph: WebPageMetadataServiceGraph, + webPageServiceGraph: WebPageServiceGraph, + webPageImageStoreGraph: WebPageImageStoreGraph + ) { + self.webPageRepositoryGraph = WebPageRepositoryGraph( + input: WebPageRepositoryGraphInput( + authService: authServiceGraph.authService, + metadataService: webPageMetadataServiceGraph.webPageMetadataService, + webPageService: webPageServiceGraph.webPageService + ) + ) + self.webPageImageRepositoryGraph = WebPageImageRepositoryGraph( + input: WebPageImageRepositoryGraphInput( + authService: authServiceGraph.authService, + store: webPageImageStoreGraph.webPageImageStore + ) + ) + } +} From 4f7b27445fb873e40091c5fc48e82bb6749170b6 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 15:37:17 +0900 Subject: [PATCH 11/19] =?UTF-8?q?refactor:=20Domain=20UseCase=20provider?= =?UTF-8?q?=20graph=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application/Domain/Project.swift | 3 +- .../Sources/Graph/AnalyticsUseCaseGraph.swift | 24 +++++++ .../Sources/Graph/AppUpdateUseCaseGraph.swift | 24 +++++++ .../Graph/AuthProviderUseCaseGraph.swift | 34 +++++++++ .../Graph/AuthSessionUseCaseGraph.swift | 24 +++++++ .../Graph/AuthenticationUseCaseGraph.swift | 34 +++++++++ .../Graph/DevelopmentGoalUseCaseGraph.swift | 39 +++++++++++ ...evelopmentRecordMutationUseCaseGraph.swift | 44 ++++++++++++ .../DevelopmentRecordQueryUseCaseGraph.swift | 29 ++++++++ .../NetworkConnectivityUseCaseGraph.swift | 24 +++++++ .../Graph/ProfileImageDataUseCaseGraph.swift | 24 +++++++ .../Graph/PushNotificationUseCaseGraph.swift | 54 +++++++++++++++ .../Graph/TodoCategoryUseCaseGraph.swift | 29 ++++++++ .../Sources/Graph/TodoGoalUseCaseGraph.swift | 29 ++++++++ .../Sources/Graph/TodoUseCaseGraph.swift | 49 +++++++++++++ .../Sources/Graph/UserDataUseCaseGraph.swift | 29 ++++++++ .../Graph/UserPreferencesUseCaseGraph.swift | 69 +++++++++++++++++++ .../Graph/WebPageImageUseCaseGraph.swift | 29 ++++++++ .../Sources/Graph/WebPageUseCaseGraph.swift | 39 +++++++++++ 19 files changed, 629 insertions(+), 1 deletion(-) create mode 100644 Application/Domain/Sources/Graph/AnalyticsUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/AppUpdateUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/AuthProviderUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/AuthSessionUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/AuthenticationUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/DevelopmentGoalUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/DevelopmentRecordMutationUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/DevelopmentRecordQueryUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/NetworkConnectivityUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/ProfileImageDataUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/PushNotificationUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/TodoCategoryUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/TodoGoalUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/TodoUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/UserDataUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/UserPreferencesUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/WebPageImageUseCaseGraph.swift create mode 100644 Application/Domain/Sources/Graph/WebPageUseCaseGraph.swift diff --git a/Application/Domain/Project.swift b/Application/Domain/Project.swift index 0c7d9f0d..4d7e1e62 100644 --- a/Application/Domain/Project.swift +++ b/Application/Domain/Project.swift @@ -9,7 +9,8 @@ let project = Project.devlogFramework( testsInfoPlistPath: "../Shared/InfoPlists/UnitTests-Info.plist", packages: [], dependencies: [ - .project(target: "Core", path: "../Core") + .project(target: "Core", path: "../Core"), + .project(target: "ThirdParty", path: "../../Libraries/ThirdParty"), ], hasTests: true ) diff --git a/Application/Domain/Sources/Graph/AnalyticsUseCaseGraph.swift b/Application/Domain/Sources/Graph/AnalyticsUseCaseGraph.swift new file mode 100644 index 00000000..3287abe9 --- /dev/null +++ b/Application/Domain/Sources/Graph/AnalyticsUseCaseGraph.swift @@ -0,0 +1,24 @@ +// +// AnalyticsUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct AnalyticsUseCaseGraphInput { + public let repository: AnalyticsRepository + + public init(repository: AnalyticsRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: AnalyticsUseCaseGraphInput.self) +public final class AnalyticsUseCaseGraph { + @Provide + private func makeTrackAnalyticsEventUseCase() -> TrackAnalyticsEventUseCase { + TrackAnalyticsEventUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/AppUpdateUseCaseGraph.swift b/Application/Domain/Sources/Graph/AppUpdateUseCaseGraph.swift new file mode 100644 index 00000000..394c2e87 --- /dev/null +++ b/Application/Domain/Sources/Graph/AppUpdateUseCaseGraph.swift @@ -0,0 +1,24 @@ +// +// AppUpdateUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct AppUpdateUseCaseGraphInput { + public let repository: AppVersionRepository + + public init(repository: AppVersionRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: AppUpdateUseCaseGraphInput.self) +public final class AppUpdateUseCaseGraph { + @Provide + private func makeCheckAppUpdateUseCase() -> CheckAppUpdateUseCase { + CheckAppUpdateUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/AuthProviderUseCaseGraph.swift b/Application/Domain/Sources/Graph/AuthProviderUseCaseGraph.swift new file mode 100644 index 00000000..13c7e51f --- /dev/null +++ b/Application/Domain/Sources/Graph/AuthProviderUseCaseGraph.swift @@ -0,0 +1,34 @@ +// +// AuthProviderUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct AuthProviderUseCaseGraphInput { + public let repository: AuthDataRepository + + public init(repository: AuthDataRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: AuthProviderUseCaseGraphInput.self) +public final class AuthProviderUseCaseGraph { + @Provide + private func makeFetchAuthProvidersUseCase() -> FetchAuthProvidersUseCase { + FetchAuthProvidersUseCaseImpl(input.repository) + } + + @Provide + private func makeLinkAuthProviderUseCase() -> LinkAuthProviderUseCase { + LinkAuthProviderUseCaseImpl(input.repository) + } + + @Provide + private func makeUnlinkAuthProviderUseCase() -> UnlinkAuthProviderUseCase { + UnlinkAuthProviderUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/AuthSessionUseCaseGraph.swift b/Application/Domain/Sources/Graph/AuthSessionUseCaseGraph.swift new file mode 100644 index 00000000..0b5cce7d --- /dev/null +++ b/Application/Domain/Sources/Graph/AuthSessionUseCaseGraph.swift @@ -0,0 +1,24 @@ +// +// AuthSessionUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct AuthSessionUseCaseGraphInput { + public let repository: AuthSessionRepository + + public init(repository: AuthSessionRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: AuthSessionUseCaseGraphInput.self) +public final class AuthSessionUseCaseGraph { + @Provide + private func makeObserveAuthSessionUseCase() -> ObserveAuthSessionUseCase { + ObserveAuthSessionUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/AuthenticationUseCaseGraph.swift b/Application/Domain/Sources/Graph/AuthenticationUseCaseGraph.swift new file mode 100644 index 00000000..83e0e847 --- /dev/null +++ b/Application/Domain/Sources/Graph/AuthenticationUseCaseGraph.swift @@ -0,0 +1,34 @@ +// +// AuthenticationUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct AuthenticationUseCaseGraphInput { + public let repository: AuthenticationRepository + + public init(repository: AuthenticationRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: AuthenticationUseCaseGraphInput.self) +public final class AuthenticationUseCaseGraph { + @Provide + private func makeSignInUseCase() -> SignInUseCase { + SignInUseCaseImpl(input.repository) + } + + @Provide + private func makeSignOutUseCase() -> SignOutUseCase { + SignOutUseCaseImpl(input.repository) + } + + @Provide + private func makeDeleteAuthUseCase() -> DeleteAuthUseCase { + DeleteAuthUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/DevelopmentGoalUseCaseGraph.swift b/Application/Domain/Sources/Graph/DevelopmentGoalUseCaseGraph.swift new file mode 100644 index 00000000..c534ac37 --- /dev/null +++ b/Application/Domain/Sources/Graph/DevelopmentGoalUseCaseGraph.swift @@ -0,0 +1,39 @@ +// +// DevelopmentGoalUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct DevelopmentGoalUseCaseGraphInput { + public let repository: DevelopmentGoalRepository + + public init(repository: DevelopmentGoalRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: DevelopmentGoalUseCaseGraphInput.self) +public final class DevelopmentGoalUseCaseGraph { + @Provide + private func makeCreateDevelopmentGoalUseCase() -> CreateDevelopmentGoalUseCase { + CreateDevelopmentGoalUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchDevelopmentGoalUseCase() -> FetchDevelopmentGoalUseCase { + FetchDevelopmentGoalUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchDevelopmentGoalsUseCase() -> FetchDevelopmentGoalsUseCase { + FetchDevelopmentGoalsUseCaseImpl(input.repository) + } + + @Provide + private func makeUpdateDevelopmentGoalStatusUseCase() -> UpdateDevelopmentGoalStatusUseCase { + UpdateDevelopmentGoalStatusUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/DevelopmentRecordMutationUseCaseGraph.swift b/Application/Domain/Sources/Graph/DevelopmentRecordMutationUseCaseGraph.swift new file mode 100644 index 00000000..199a0af8 --- /dev/null +++ b/Application/Domain/Sources/Graph/DevelopmentRecordMutationUseCaseGraph.swift @@ -0,0 +1,44 @@ +// +// DevelopmentRecordMutationUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct DevelopmentRecordMutationGraphInput { + public let repository: DevelopmentRecordRepository + public let goalRepository: DevelopmentGoalRepository + + public init( + repository: DevelopmentRecordRepository, + goalRepository: DevelopmentGoalRepository + ) { + self.repository = repository + self.goalRepository = goalRepository + } +} + +@DependencyGraph(input: DevelopmentRecordMutationGraphInput.self) +public final class DevelopmentRecordMutationUseCaseGraph { + @Provide + private func makeCreateDevelopmentRecordUseCase() -> CreateDevelopmentRecordUseCase { + CreateDevelopmentRecordUseCaseImpl(input.repository, input.goalRepository) + } + + @Provide + private func makeSaveDevelopmentRecordDraftUseCase() -> SaveDevelopmentRecordDraftUseCase { + SaveDevelopmentRecordDraftUseCaseImpl(input.repository, input.goalRepository) + } + + @Provide + private func makeConfirmDevelopmentRecordUseCase() -> ConfirmDevelopmentRecordUseCase { + ConfirmDevelopmentRecordUseCaseImpl(input.repository, input.goalRepository) + } + + @Provide + private func makeRestoreDevelopmentRecordUseCase() -> RestoreDevelopmentRecordUseCase { + RestoreDevelopmentRecordUseCaseImpl(input.repository, input.goalRepository) + } +} diff --git a/Application/Domain/Sources/Graph/DevelopmentRecordQueryUseCaseGraph.swift b/Application/Domain/Sources/Graph/DevelopmentRecordQueryUseCaseGraph.swift new file mode 100644 index 00000000..4c689c4a --- /dev/null +++ b/Application/Domain/Sources/Graph/DevelopmentRecordQueryUseCaseGraph.swift @@ -0,0 +1,29 @@ +// +// DevelopmentRecordQueryUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct DevelopmentRecordQueryUseCaseGraphInput { + public let repository: DevelopmentRecordRepository + + public init(repository: DevelopmentRecordRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: DevelopmentRecordQueryUseCaseGraphInput.self) +public final class DevelopmentRecordQueryUseCaseGraph { + @Provide + private func makeFetchDevelopmentRecordsUseCase() -> FetchDevelopmentRecordsUseCase { + FetchDevelopmentRecordsUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchDevelopmentRecordHistoryUseCase() -> FetchDevelopmentRecordHistoryUseCase { + FetchDevelopmentRecordHistoryUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/NetworkConnectivityUseCaseGraph.swift b/Application/Domain/Sources/Graph/NetworkConnectivityUseCaseGraph.swift new file mode 100644 index 00000000..958999b2 --- /dev/null +++ b/Application/Domain/Sources/Graph/NetworkConnectivityUseCaseGraph.swift @@ -0,0 +1,24 @@ +// +// NetworkConnectivityUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct NetworkConnectivityUseCaseGraphInput { + public let repository: NetworkConnectivityRepository + + public init(repository: NetworkConnectivityRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: NetworkConnectivityUseCaseGraphInput.self) +public final class NetworkConnectivityUseCaseGraph { + @Provide + private func makeObserveNetworkConnectivityUseCase() -> ObserveNetworkConnectivityUseCase { + ObserveNetworkConnectivityUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/ProfileImageDataUseCaseGraph.swift b/Application/Domain/Sources/Graph/ProfileImageDataUseCaseGraph.swift new file mode 100644 index 00000000..9af7b917 --- /dev/null +++ b/Application/Domain/Sources/Graph/ProfileImageDataUseCaseGraph.swift @@ -0,0 +1,24 @@ +// +// ProfileImageDataUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct ProfileImageDataUseCaseGraphInput { + public let repository: ProfileImageDataRepository + + public init(repository: ProfileImageDataRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: ProfileImageDataUseCaseGraphInput.self) +public final class ProfileImageDataUseCaseGraph { + @Provide + private func makeFetchProfileImageDataUseCase() -> FetchProfileImageDataUseCase { + FetchProfileImageDataUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/PushNotificationUseCaseGraph.swift b/Application/Domain/Sources/Graph/PushNotificationUseCaseGraph.swift new file mode 100644 index 00000000..d5443ae1 --- /dev/null +++ b/Application/Domain/Sources/Graph/PushNotificationUseCaseGraph.swift @@ -0,0 +1,54 @@ +// +// PushNotificationUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct PushNotificationUseCaseGraphInput { + public let repository: PushNotificationRepository + + public init(repository: PushNotificationRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: PushNotificationUseCaseGraphInput.self) +public final class PushNotificationUseCaseGraph { + @Provide + private func makeFetchPushSettingsUseCase() -> FetchPushSettingsUseCase { + FetchPushSettingsUseCaseImpl(input.repository) + } + + @Provide + private func makeUpdatePushSettingsUseCase() -> UpdatePushSettingsUseCase { + UpdatePushSettingsUseCaseImpl(input.repository) + } + + @Provide + private func makeDeletePushNotificationUseCase() -> DeletePushNotificationUseCase { + DeletePushNotificationUseCaseImpl(input.repository) + } + + @Provide + private func makeUndoDeletePushNotificationUseCase() -> UndoDeletePushNotificationUseCase { + UndoDeletePushNotificationUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchPushNotificationsUseCase() -> FetchPushNotificationsUseCase { + FetchPushNotificationsUseCaseImpl(input.repository) + } + + @Provide + private func makeObserveUnreadPushCountUseCase() -> ObserveUnreadPushCountUseCase { + ObserveUnreadPushCountUseCaseImpl(input.repository) + } + + @Provide + private func makeTogglePushNotificationReadUseCase() -> TogglePushNotificationReadUseCase { + TogglePushNotificationReadUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/TodoCategoryUseCaseGraph.swift b/Application/Domain/Sources/Graph/TodoCategoryUseCaseGraph.swift new file mode 100644 index 00000000..280a3c38 --- /dev/null +++ b/Application/Domain/Sources/Graph/TodoCategoryUseCaseGraph.swift @@ -0,0 +1,29 @@ +// +// TodoCategoryUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct TodoCategoryUseCaseGraphInput { + public let todoCategoryRepository: TodoCategoryRepository + + public init(todoCategoryRepository: TodoCategoryRepository) { + self.todoCategoryRepository = todoCategoryRepository + } +} + +@DependencyGraph(input: TodoCategoryUseCaseGraphInput.self) +public final class TodoCategoryUseCaseGraph { + @Provide + private func makeFetchTodoCategoryPreferencesUseCase() -> FetchTodoCategoryPreferencesUseCase { + FetchTodoCategoryPreferencesUseCaseImpl(input.todoCategoryRepository) + } + + @Provide + private func makeUpdateTodoCategoryPreferencesUseCase() -> UpdateTodoCategoryPreferencesUseCase { + UpdateTodoCategoryPreferencesUseCaseImpl(input.todoCategoryRepository) + } +} diff --git a/Application/Domain/Sources/Graph/TodoGoalUseCaseGraph.swift b/Application/Domain/Sources/Graph/TodoGoalUseCaseGraph.swift new file mode 100644 index 00000000..e3ba86f1 --- /dev/null +++ b/Application/Domain/Sources/Graph/TodoGoalUseCaseGraph.swift @@ -0,0 +1,29 @@ +// +// TodoGoalUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct TodoGoalUseCaseGraphInput { + public let todoRepository: TodoRepository + public let goalRepository: DevelopmentGoalRepository + + public init( + todoRepository: TodoRepository, + goalRepository: DevelopmentGoalRepository + ) { + self.todoRepository = todoRepository + self.goalRepository = goalRepository + } +} + +@DependencyGraph(input: TodoGoalUseCaseGraphInput.self) +public final class TodoGoalUseCaseGraph { + @Provide + private func makeUpdateTodoGoalUseCase() -> UpdateTodoGoalUseCase { + UpdateTodoGoalUseCaseImpl(input.todoRepository, input.goalRepository) + } +} diff --git a/Application/Domain/Sources/Graph/TodoUseCaseGraph.swift b/Application/Domain/Sources/Graph/TodoUseCaseGraph.swift new file mode 100644 index 00000000..111bd001 --- /dev/null +++ b/Application/Domain/Sources/Graph/TodoUseCaseGraph.swift @@ -0,0 +1,49 @@ +// +// TodoUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct TodoUseCaseGraphInput { + public let repository: TodoRepository + + public init(repository: TodoRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: TodoUseCaseGraphInput.self) +public final class TodoUseCaseGraph { + @Provide + private func makeFetchTodoByIdUseCase() -> FetchTodoByIdUseCase { + FetchTodoByIdUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchReferenceItemsUseCase() -> FetchReferenceItemsUseCase { + FetchReferenceItemsUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchTodosUseCase() -> FetchTodosUseCase { + FetchTodosUseCaseImpl(input.repository) + } + + @Provide + private func makeUpsertTodoUseCase() -> UpsertTodoUseCase { + UpsertTodoUseCaseImpl(input.repository) + } + + @Provide + private func makeDeleteTodoUseCase() -> DeleteTodoUseCase { + DeleteTodoUseCaseImpl(input.repository) + } + + @Provide + private func makeUndoDeleteTodoUseCase() -> UndoDeleteTodoUseCase { + UndoDeleteTodoUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/UserDataUseCaseGraph.swift b/Application/Domain/Sources/Graph/UserDataUseCaseGraph.swift new file mode 100644 index 00000000..d7abe6b8 --- /dev/null +++ b/Application/Domain/Sources/Graph/UserDataUseCaseGraph.swift @@ -0,0 +1,29 @@ +// +// UserDataUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct UserDataUseCaseGraphInput { + public let repository: UserDataRepository + + public init(repository: UserDataRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: UserDataUseCaseGraphInput.self) +public final class UserDataUseCaseGraph { + @Provide + private func makeFetchUserDataUseCase() -> FetchUserDataUseCase { + FetchUserDataUseCaseImpl(input.repository) + } + + @Provide + private func makeUpsertStatusMessageUseCase() -> UpsertStatusMessageUseCase { + UpsertStatusMessageUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/UserPreferencesUseCaseGraph.swift b/Application/Domain/Sources/Graph/UserPreferencesUseCaseGraph.swift new file mode 100644 index 00000000..982e2cee --- /dev/null +++ b/Application/Domain/Sources/Graph/UserPreferencesUseCaseGraph.swift @@ -0,0 +1,69 @@ +// +// UserPreferencesUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct UserPreferencesUseCaseGraphInput { + public let repository: UserPreferencesRepository + + public init(repository: UserPreferencesRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: UserPreferencesUseCaseGraphInput.self) +public final class UserPreferencesUseCaseGraph { + @Provide + private func makeObserveSystemThemeUseCase() -> ObserveSystemThemeUseCase { + ObserveSystemThemeUseCaseImpl(input.repository) + } + + @Provide + private func makeUpdateSystemThemeUseCase() -> UpdateSystemThemeUseCase { + UpdateSystemThemeUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchRecentSearchQueriesUseCase() -> FetchRecentSearchQueriesUseCase { + FetchRecentSearchQueriesUseCaseImpl(input.repository) + } + + @Provide + private func makeUpdateRecentSearchQueriesUseCase() -> UpdateRecentSearchQueriesUseCase { + UpdateRecentSearchQueriesUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchPushNotificationQueryUseCase() -> FetchPushNotificationQueryUseCase { + FetchPushNotificationQueryUseCaseImpl(input.repository) + } + + @Provide + private func makeUpdatePushNotificationQueryUseCase() -> UpdatePushNotificationQueryUseCase { + UpdatePushNotificationQueryUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchHeatmapActivityTypesUseCase() -> FetchHeatmapActivityTypesUseCase { + FetchHeatmapActivityTypesUseCaseImpl(input.repository) + } + + @Provide + private func makeUpdateHeatmapActivityTypesUseCase() -> UpdateHeatmapActivityTypesUseCase { + UpdateHeatmapActivityTypesUseCaseImpl(input.repository) + } + + @Provide + private func makeFetchTodayDisplayOptionsUseCase() -> FetchTodayDisplayOptionsUseCase { + FetchTodayDisplayOptionsUseCaseImpl(input.repository) + } + + @Provide + private func makeUpdateTodayDisplayOptionsUseCase() -> UpdateTodayDisplayOptionsUseCase { + UpdateTodayDisplayOptionsUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/WebPageImageUseCaseGraph.swift b/Application/Domain/Sources/Graph/WebPageImageUseCaseGraph.swift new file mode 100644 index 00000000..8f21adc8 --- /dev/null +++ b/Application/Domain/Sources/Graph/WebPageImageUseCaseGraph.swift @@ -0,0 +1,29 @@ +// +// WebPageImageUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct WebPageImageUseCaseGraphInput { + public let repository: WebPageImageRepository + + public init(repository: WebPageImageRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: WebPageImageUseCaseGraphInput.self) +public final class WebPageImageUseCaseGraph { + @Provide + private func makeFetchWebPageImageDirSizeUseCase() -> FetchWebPageImageDirSizeUseCase { + FetchWebPageImageDirSizeUseCaseImpl(input.repository) + } + + @Provide + private func makeClearWebPageImageDirectoryUseCase() -> ClearWebPageImageDirectoryUseCase { + ClearWebPageImageDirectoryUseCaseImpl(input.repository) + } +} diff --git a/Application/Domain/Sources/Graph/WebPageUseCaseGraph.swift b/Application/Domain/Sources/Graph/WebPageUseCaseGraph.swift new file mode 100644 index 00000000..ac3ef267 --- /dev/null +++ b/Application/Domain/Sources/Graph/WebPageUseCaseGraph.swift @@ -0,0 +1,39 @@ +// +// WebPageUseCaseGraph.swift +// Domain +// +// Created by opfic on 9/7/26. +// + +import Cradle + +public struct WebPageUseCaseGraphInput { + public let repository: WebPageRepository + + public init(repository: WebPageRepository) { + self.repository = repository + } +} + +@DependencyGraph(input: WebPageUseCaseGraphInput.self) +public final class WebPageUseCaseGraph { + @Provide + private func makeFetchWebPagesUseCase() -> FetchWebPagesUseCase { + FetchWebPagesUseCaseImpl(input.repository) + } + + @Provide + private func makeAddWebPageUseCase() -> AddWebPageUseCase { + AddWebPageUseCaseImpl(input.repository) + } + + @Provide + private func makeDeleteWebPageUseCase() -> DeleteWebPageUseCase { + DeleteWebPageUseCaseImpl(input.repository) + } + + @Provide + private func makeUndoDeleteWebPageUseCase() -> UndoDeleteWebPageUseCase { + UndoDeleteWebPageUseCaseImpl(input.repository) + } +} From 89b66f406a9ba05a6f60963cfc20bb57c62f37ca Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 16:00:32 +0900 Subject: [PATCH 12/19] =?UTF-8?q?refactor:=20=EA=B8=B0=EB=8A=A5=EB=B3=84?= =?UTF-8?q?=20GraphSet=20=EC=A1=B0=EB=A6=BD=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/App/Graph/AnalyticsGraphSet.swift | 28 +++++++++++ .../Sources/App/Graph/AppUpdateGraphSet.swift | 28 +++++++++++ ...Set.swift => AuthenticationGraphSet.swift} | 37 ++++++++++++-- .../App/Graph/DevelopmentGraphSet.swift | 50 +++++++++++++++++++ .../Graph/DevelopmentRepositoryGraphSet.swift | 30 ----------- .../Graph/NetworkConnectivityGraphSet.swift | 28 +++++++++++ .../App/Graph/PushNotificationGraphSet.swift | 35 +++++++++++++ ...itoryGraphSet.swift => TodoGraphSet.swift} | 27 ++++++++-- .../App/Graph/UserPreferencesGraphSet.swift | 37 ++++++++++++++ .../App/Graph/UserProfileGraphSet.swift | 46 +++++++++++++++++ ...ryGraphSet.swift => WebPageGraphSet.swift} | 17 ++++++- 11 files changed, 325 insertions(+), 38 deletions(-) create mode 100644 Application/App/Sources/App/Graph/AnalyticsGraphSet.swift create mode 100644 Application/App/Sources/App/Graph/AppUpdateGraphSet.swift rename Application/App/Sources/App/Graph/{AuthenticationRepositoryGraphSet.swift => AuthenticationGraphSet.swift} (51%) create mode 100644 Application/App/Sources/App/Graph/DevelopmentGraphSet.swift delete mode 100644 Application/App/Sources/App/Graph/DevelopmentRepositoryGraphSet.swift create mode 100644 Application/App/Sources/App/Graph/NetworkConnectivityGraphSet.swift create mode 100644 Application/App/Sources/App/Graph/PushNotificationGraphSet.swift rename Application/App/Sources/App/Graph/{TodoRepositoryGraphSet.swift => TodoGraphSet.swift} (62%) create mode 100644 Application/App/Sources/App/Graph/UserPreferencesGraphSet.swift create mode 100644 Application/App/Sources/App/Graph/UserProfileGraphSet.swift rename Application/App/Sources/App/Graph/{WebPageRepositoryGraphSet.swift => WebPageGraphSet.swift} (64%) diff --git a/Application/App/Sources/App/Graph/AnalyticsGraphSet.swift b/Application/App/Sources/App/Graph/AnalyticsGraphSet.swift new file mode 100644 index 00000000..3ce0504e --- /dev/null +++ b/Application/App/Sources/App/Graph/AnalyticsGraphSet.swift @@ -0,0 +1,28 @@ +// +// AnalyticsGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Domain +import Infra + +final class AnalyticsGraphSet { + let analyticsRepositoryGraph: AnalyticsRepositoryGraph + let analyticsUseCaseGraph: AnalyticsUseCaseGraph + + init(analyticsServiceGraph: AnalyticsServiceGraph) { + self.analyticsRepositoryGraph = AnalyticsRepositoryGraph( + input: AnalyticsRepositoryGraphInput( + analyticsService: analyticsServiceGraph.analyticsService + ) + ) + self.analyticsUseCaseGraph = AnalyticsUseCaseGraph( + input: AnalyticsUseCaseGraphInput( + repository: analyticsRepositoryGraph.analyticsRepository + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/AppUpdateGraphSet.swift b/Application/App/Sources/App/Graph/AppUpdateGraphSet.swift new file mode 100644 index 00000000..c1d0ec16 --- /dev/null +++ b/Application/App/Sources/App/Graph/AppUpdateGraphSet.swift @@ -0,0 +1,28 @@ +// +// AppUpdateGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Domain +import Infra + +final class AppUpdateGraphSet { + let appVersionRepositoryGraph: AppVersionRepositoryGraph + let appUpdateUseCaseGraph: AppUpdateUseCaseGraph + + init(appStoreVersionServiceGraph: AppStoreVersionServiceGraph) { + self.appVersionRepositoryGraph = AppVersionRepositoryGraph( + input: AppVersionRepositoryGraphInput( + service: appStoreVersionServiceGraph.appStoreVersionService + ) + ) + self.appUpdateUseCaseGraph = AppUpdateUseCaseGraph( + input: AppUpdateUseCaseGraphInput( + repository: appVersionRepositoryGraph.appVersionRepository + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/AuthenticationRepositoryGraphSet.swift b/Application/App/Sources/App/Graph/AuthenticationGraphSet.swift similarity index 51% rename from Application/App/Sources/App/Graph/AuthenticationRepositoryGraphSet.swift rename to Application/App/Sources/App/Graph/AuthenticationGraphSet.swift index fb2144ef..26422662 100644 --- a/Application/App/Sources/App/Graph/AuthenticationRepositoryGraphSet.swift +++ b/Application/App/Sources/App/Graph/AuthenticationGraphSet.swift @@ -1,17 +1,27 @@ // -// AuthenticationRepositoryGraphSet.swift +// AuthenticationGraphSet.swift // App // // Created by opfic on 9/7/26. // import Data +import Domain import Infra +import Persistence import Widget -final class AuthenticationRepositoryGraphSet { +final class AuthenticationGraphSet { let authenticationRepositoryGraph: AuthenticationRepositoryGraph let authDataRepositoryGraph: AuthDataRepositoryGraph + let authSessionRepositoryGraph: AuthSessionRepositoryGraph + let authenticationUseCaseGraph: AuthenticationUseCaseGraph + let authProviderUseCaseGraph: AuthProviderUseCaseGraph + private(set) lazy var authSessionUseCaseGraph = AuthSessionUseCaseGraph( + input: AuthSessionUseCaseGraphInput( + repository: authSessionRepositoryGraph.authSessionRepository + ) + ) init( authServiceGraph: AuthServiceGraph, @@ -19,7 +29,10 @@ final class AuthenticationRepositoryGraphSet { githubAuthenticationServiceGraph: GithubAuthenticationServiceGraph, googleAuthenticationServiceGraph: GoogleAuthenticationServiceGraph, userServiceGraph: UserServiceGraph, - widgetSnapshotUpdaterGraph: WidgetSnapshotUpdaterGraph + todoCategoryServiceGraph: TodoCategoryServiceGraph, + memoryCacheStoreGraph: MemoryCacheStoreGraph, + widgetSnapshotUpdaterGraph: WidgetSnapshotUpdaterGraph, + authSessionStateProviderGraph: AuthSessionStateProviderGraph ) { self.authenticationRepositoryGraph = AuthenticationRepositoryGraph( input: AuthenticationRepositoryGraphInput( @@ -39,5 +52,23 @@ final class AuthenticationRepositoryGraphSet { googleAuthService: googleAuthenticationServiceGraph.googleAuthenticationService ) ) + self.authSessionRepositoryGraph = AuthSessionRepositoryGraph( + input: AuthSessionRepositoryGraphInput( + authService: authServiceGraph.authService, + todoCategoryService: todoCategoryServiceGraph.todoCategoryService, + store: memoryCacheStoreGraph.memoryCacheStore, + provider: authSessionStateProviderGraph.authSessionStateProvider + ) + ) + self.authenticationUseCaseGraph = AuthenticationUseCaseGraph( + input: AuthenticationUseCaseGraphInput( + repository: authenticationRepositoryGraph.authenticationRepository + ) + ) + self.authProviderUseCaseGraph = AuthProviderUseCaseGraph( + input: AuthProviderUseCaseGraphInput( + repository: authDataRepositoryGraph.authDataRepository + ) + ) } } diff --git a/Application/App/Sources/App/Graph/DevelopmentGraphSet.swift b/Application/App/Sources/App/Graph/DevelopmentGraphSet.swift new file mode 100644 index 00000000..d83ad199 --- /dev/null +++ b/Application/App/Sources/App/Graph/DevelopmentGraphSet.swift @@ -0,0 +1,50 @@ +// +// DevelopmentGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Domain +import Infra + +final class DevelopmentGraphSet { + let developmentGoalRepositoryGraph: DevelopmentGoalRepositoryGraph + let developmentRecordRepositoryGraph: DevelopmentRecordRepositoryGraph + let developmentGoalUseCaseGraph: DevelopmentGoalUseCaseGraph + let developmentRecordQueryUseCaseGraph: DevelopmentRecordQueryUseCaseGraph + let developmentRecordMutationUseCaseGraph: DevelopmentRecordMutationUseCaseGraph + + init( + developmentGoalServiceGraph: DevelopmentGoalServiceGraph, + developmentRecordServiceGraph: DevelopmentRecordServiceGraph + ) { + self.developmentGoalRepositoryGraph = DevelopmentGoalRepositoryGraph( + input: DevelopmentGoalRepositoryGraphInput( + service: developmentGoalServiceGraph.developmentGoalService + ) + ) + self.developmentRecordRepositoryGraph = DevelopmentRecordRepositoryGraph( + input: DevelopmentRecordRepositoryGraphInput( + service: developmentRecordServiceGraph.developmentRecordService + ) + ) + self.developmentGoalUseCaseGraph = DevelopmentGoalUseCaseGraph( + input: DevelopmentGoalUseCaseGraphInput( + repository: developmentGoalRepositoryGraph.developmentGoalRepository + ) + ) + self.developmentRecordQueryUseCaseGraph = DevelopmentRecordQueryUseCaseGraph( + input: DevelopmentRecordQueryUseCaseGraphInput( + repository: developmentRecordRepositoryGraph.developmentRecordRepository + ) + ) + self.developmentRecordMutationUseCaseGraph = DevelopmentRecordMutationUseCaseGraph( + input: DevelopmentRecordMutationGraphInput( + repository: developmentRecordRepositoryGraph.developmentRecordRepository, + goalRepository: developmentGoalRepositoryGraph.developmentGoalRepository + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/DevelopmentRepositoryGraphSet.swift b/Application/App/Sources/App/Graph/DevelopmentRepositoryGraphSet.swift deleted file mode 100644 index 40b4c0de..00000000 --- a/Application/App/Sources/App/Graph/DevelopmentRepositoryGraphSet.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// DevelopmentRepositoryGraphSet.swift -// App -// -// Created by opfic on 9/7/26. -// - -import Data -import Infra - -final class DevelopmentRepositoryGraphSet { - let developmentGoalRepositoryGraph: DevelopmentGoalRepositoryGraph - let developmentRecordRepositoryGraph: DevelopmentRecordRepositoryGraph - - init( - developmentGoalServiceGraph: DevelopmentGoalServiceGraph, - developmentRecordServiceGraph: DevelopmentRecordServiceGraph - ) { - self.developmentGoalRepositoryGraph = DevelopmentGoalRepositoryGraph( - input: DevelopmentGoalRepositoryGraphInput( - service: developmentGoalServiceGraph.developmentGoalService - ) - ) - self.developmentRecordRepositoryGraph = DevelopmentRecordRepositoryGraph( - input: DevelopmentRecordRepositoryGraphInput( - service: developmentRecordServiceGraph.developmentRecordService - ) - ) - } -} diff --git a/Application/App/Sources/App/Graph/NetworkConnectivityGraphSet.swift b/Application/App/Sources/App/Graph/NetworkConnectivityGraphSet.swift new file mode 100644 index 00000000..e30cc503 --- /dev/null +++ b/Application/App/Sources/App/Graph/NetworkConnectivityGraphSet.swift @@ -0,0 +1,28 @@ +// +// NetworkConnectivityGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Domain +import Infra + +final class NetworkConnectivityGraphSet { + private let networkConnectivityProviderGraph: NWPathConnectivityProviderGraph + private(set) lazy var networkConnectivityRepositoryGraph = NetworkConnectivityRepositoryGraph( + input: NetworkConnectivityRepositoryGraphInput( + connectivityProvider: networkConnectivityProviderGraph.nwPathConnectivityProvider + ) + ) + private(set) lazy var networkConnectivityUseCaseGraph = NetworkConnectivityUseCaseGraph( + input: NetworkConnectivityUseCaseGraphInput( + repository: networkConnectivityRepositoryGraph.networkConnectivityRepository + ) + ) + + init(networkConnectivityProviderGraph: NWPathConnectivityProviderGraph) { + self.networkConnectivityProviderGraph = networkConnectivityProviderGraph + } +} diff --git a/Application/App/Sources/App/Graph/PushNotificationGraphSet.swift b/Application/App/Sources/App/Graph/PushNotificationGraphSet.swift new file mode 100644 index 00000000..fed8ad0a --- /dev/null +++ b/Application/App/Sources/App/Graph/PushNotificationGraphSet.swift @@ -0,0 +1,35 @@ +// +// PushNotificationGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Domain +import Infra +import Persistence + +final class PushNotificationGraphSet { + let pushNotificationRepositoryGraph: PushNotificationRepositoryGraph + let pushNotificationUseCaseGraph: PushNotificationUseCaseGraph + + init( + pushNotificationServiceGraph: PushNotificationServiceGraph, + todoCategoryServiceGraph: TodoCategoryServiceGraph, + memoryCacheStoreGraph: MemoryCacheStoreGraph + ) { + self.pushNotificationRepositoryGraph = PushNotificationRepositoryGraph( + input: PushNotificationRepositoryGraphInput( + pushNotificationService: pushNotificationServiceGraph.pushNotificationService, + todoCategoryService: todoCategoryServiceGraph.todoCategoryService, + store: memoryCacheStoreGraph.memoryCacheStore + ) + ) + self.pushNotificationUseCaseGraph = PushNotificationUseCaseGraph( + input: PushNotificationUseCaseGraphInput( + repository: pushNotificationRepositoryGraph.pushNotificationRepository + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/TodoRepositoryGraphSet.swift b/Application/App/Sources/App/Graph/TodoGraphSet.swift similarity index 62% rename from Application/App/Sources/App/Graph/TodoRepositoryGraphSet.swift rename to Application/App/Sources/App/Graph/TodoGraphSet.swift index 6b6d45b1..abd92b31 100644 --- a/Application/App/Sources/App/Graph/TodoRepositoryGraphSet.swift +++ b/Application/App/Sources/App/Graph/TodoGraphSet.swift @@ -1,27 +1,32 @@ // -// TodoRepositoryGraphSet.swift +// TodoGraphSet.swift // App // // Created by opfic on 9/7/26. // import Data +import Domain import Infra import Persistence import Widget -final class TodoRepositoryGraphSet { +final class TodoGraphSet { let todoMutationEventBusGraph = TodoMutationEventBusGraph() let todoRepositoryGraph: TodoRepositoryGraph let todoCategoryRepositoryGraph: TodoCategoryRepositoryGraph let widgetTodoSnapshotRepositoryGraph: WidgetTodoSnapshotRepositoryGraph + let todoUseCaseGraph: TodoUseCaseGraph + let todoCategoryUseCaseGraph: TodoCategoryUseCaseGraph + let todoGoalUseCaseGraph: TodoGoalUseCaseGraph init( todoQueryServiceGraph: TodoQueryServiceGraph, todoCommandServiceGraph: TodoCommandServiceGraph, todoCategoryServiceGraph: TodoCategoryServiceGraph, memoryCacheStoreGraph: MemoryCacheStoreGraph, - widgetSnapshotUpdaterGraph: WidgetSnapshotUpdaterGraph + widgetSnapshotUpdaterGraph: WidgetSnapshotUpdaterGraph, + developmentGoalRepositoryGraph: DevelopmentGoalRepositoryGraph ) { self.todoRepositoryGraph = TodoRepositoryGraph( input: TodoRepositoryGraphInput( @@ -44,5 +49,21 @@ final class TodoRepositoryGraphSet { queryService: todoQueryServiceGraph.todoQueryService ) ) + self.todoUseCaseGraph = TodoUseCaseGraph( + input: TodoUseCaseGraphInput( + repository: todoRepositoryGraph.todoRepository + ) + ) + self.todoCategoryUseCaseGraph = TodoCategoryUseCaseGraph( + input: TodoCategoryUseCaseGraphInput( + todoCategoryRepository: todoCategoryRepositoryGraph.todoCategoryRepository + ) + ) + self.todoGoalUseCaseGraph = TodoGoalUseCaseGraph( + input: TodoGoalUseCaseGraphInput( + todoRepository: todoRepositoryGraph.todoRepository, + goalRepository: developmentGoalRepositoryGraph.developmentGoalRepository + ) + ) } } diff --git a/Application/App/Sources/App/Graph/UserPreferencesGraphSet.swift b/Application/App/Sources/App/Graph/UserPreferencesGraphSet.swift new file mode 100644 index 00000000..9fa255d7 --- /dev/null +++ b/Application/App/Sources/App/Graph/UserPreferencesGraphSet.swift @@ -0,0 +1,37 @@ +// +// UserPreferencesGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Domain +import Persistence +import Widget + +final class UserPreferencesGraphSet { + let userPreferencesRepositoryGraph: UserPreferencesRepositoryGraph + let userPreferencesUseCaseGraph: UserPreferencesUseCaseGraph + + init( + userDefaultsStoreGraph: UserDefaultsStoreGraph, + themeStoreGraph: ThemeStoreGraph, + widgetSnapshotPreferenceStoreGraph: WidgetSnapshotPreferenceStoreGraph, + widgetSyncEventBusGraph: WidgetSyncEventBusGraph + ) { + self.userPreferencesRepositoryGraph = UserPreferencesRepositoryGraph( + input: UserPreferencesRepositoryGraphInput( + store: userDefaultsStoreGraph.userDefaultsStore, + themeStore: themeStoreGraph.themeStore, + widgetSnapshotPreferenceStore: widgetSnapshotPreferenceStoreGraph.widgetSnapshotPreferenceStore, + widgetSyncEventBus: widgetSyncEventBusGraph.widgetSyncEventBus + ) + ) + self.userPreferencesUseCaseGraph = UserPreferencesUseCaseGraph( + input: UserPreferencesUseCaseGraphInput( + repository: userPreferencesRepositoryGraph.userPreferencesRepository + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/UserProfileGraphSet.swift b/Application/App/Sources/App/Graph/UserProfileGraphSet.swift new file mode 100644 index 00000000..3d431360 --- /dev/null +++ b/Application/App/Sources/App/Graph/UserProfileGraphSet.swift @@ -0,0 +1,46 @@ +// +// UserProfileGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Domain +import Infra +import Persistence + +final class UserProfileGraphSet { + let userDataRepositoryGraph: UserDataRepositoryGraph + let profileImageDataRepositoryGraph: ProfileImageDataRepositoryGraph + let userDataUseCaseGraph: UserDataUseCaseGraph + let profileImageDataUseCaseGraph: ProfileImageDataUseCaseGraph + + init( + userServiceGraph: UserServiceGraph, + profileImageDataServiceGraph: ProfileImageDataServiceGraph, + memoryCacheStoreGraph: MemoryCacheStoreGraph + ) { + self.userDataRepositoryGraph = UserDataRepositoryGraph( + input: UserDataRepositoryGraphInput( + userService: userServiceGraph.userService + ) + ) + self.profileImageDataRepositoryGraph = ProfileImageDataRepositoryGraph( + input: ProfileImageDataRepositoryGraphInput( + service: profileImageDataServiceGraph.profileImageDataService, + store: memoryCacheStoreGraph.memoryCacheStore + ) + ) + self.userDataUseCaseGraph = UserDataUseCaseGraph( + input: UserDataUseCaseGraphInput( + repository: userDataRepositoryGraph.userDataRepository + ) + ) + self.profileImageDataUseCaseGraph = ProfileImageDataUseCaseGraph( + input: ProfileImageDataUseCaseGraphInput( + repository: profileImageDataRepositoryGraph.profileImageDataRepository + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/WebPageRepositoryGraphSet.swift b/Application/App/Sources/App/Graph/WebPageGraphSet.swift similarity index 64% rename from Application/App/Sources/App/Graph/WebPageRepositoryGraphSet.swift rename to Application/App/Sources/App/Graph/WebPageGraphSet.swift index 6e99f886..915f3c87 100644 --- a/Application/App/Sources/App/Graph/WebPageRepositoryGraphSet.swift +++ b/Application/App/Sources/App/Graph/WebPageGraphSet.swift @@ -1,17 +1,20 @@ // -// WebPageRepositoryGraphSet.swift +// WebPageGraphSet.swift // App // // Created by opfic on 9/7/26. // import Data +import Domain import Infra import Persistence -final class WebPageRepositoryGraphSet { +final class WebPageGraphSet { let webPageRepositoryGraph: WebPageRepositoryGraph let webPageImageRepositoryGraph: WebPageImageRepositoryGraph + let webPageUseCaseGraph: WebPageUseCaseGraph + let webPageImageUseCaseGraph: WebPageImageUseCaseGraph init( authServiceGraph: AuthServiceGraph, @@ -32,5 +35,15 @@ final class WebPageRepositoryGraphSet { store: webPageImageStoreGraph.webPageImageStore ) ) + self.webPageUseCaseGraph = WebPageUseCaseGraph( + input: WebPageUseCaseGraphInput( + repository: webPageRepositoryGraph.webPageRepository + ) + ) + self.webPageImageUseCaseGraph = WebPageImageUseCaseGraph( + input: WebPageImageUseCaseGraphInput( + repository: webPageImageRepositoryGraph.webPageImageRepository + ) + ) } } From 597c433218749a24c3eca3ee50641d28e453ca84 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 16:01:01 +0900 Subject: [PATCH 13/19] =?UTF-8?q?refactor:=20AppGraph=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../App/Sources/App/Graph/AppGraph.swift | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 Application/App/Sources/App/Graph/AppGraph.swift diff --git a/Application/App/Sources/App/Graph/AppGraph.swift b/Application/App/Sources/App/Graph/AppGraph.swift new file mode 100644 index 00000000..f76d7b8e --- /dev/null +++ b/Application/App/Sources/App/Graph/AppGraph.swift @@ -0,0 +1,154 @@ +// +// AppGraph.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Cradle + +@MainActor +@DependencyGraph(.shared) +final class AppGraph { + @Provide + private func makePersistenceGraphSet() -> PersistenceGraphSet { + PersistenceGraphSet() + } + + @Provide + private func makeInfraGraphSet( + persistenceGraphSet: PersistenceGraphSet + ) -> InfraGraphSet { + InfraGraphSet( + webPageImageStore: persistenceGraphSet.webPageImageStoreGraph.webPageImageStore + ) + } + + @Provide + private func makeWidgetGraphSet() -> WidgetGraphSet { + WidgetGraphSet() + } + + @Provide + private func makeDevelopmentGraphSet( + infraGraphSet: InfraGraphSet + ) -> DevelopmentGraphSet { + DevelopmentGraphSet( + developmentGoalServiceGraph: infraGraphSet.developmentGoalServiceGraph, + developmentRecordServiceGraph: infraGraphSet.developmentRecordServiceGraph + ) + } + + @Provide + private func makeAuthenticationGraphSet( + persistenceGraphSet: PersistenceGraphSet, + infraGraphSet: InfraGraphSet, + widgetGraphSet: WidgetGraphSet + ) -> AuthenticationGraphSet { + AuthenticationGraphSet( + authServiceGraph: infraGraphSet.authServiceGraph, + appleAuthenticationServiceGraph: infraGraphSet.appleAuthenticationServiceGraph, + githubAuthenticationServiceGraph: infraGraphSet.githubAuthenticationServiceGraph, + googleAuthenticationServiceGraph: infraGraphSet.googleAuthenticationServiceGraph, + userServiceGraph: infraGraphSet.userServiceGraph, + todoCategoryServiceGraph: infraGraphSet.todoCategoryServiceGraph, + memoryCacheStoreGraph: persistenceGraphSet.memoryCacheStoreGraph, + widgetSnapshotUpdaterGraph: widgetGraphSet.widgetSnapshotUpdaterGraph, + authSessionStateProviderGraph: widgetGraphSet.authSessionStateProviderGraph + ) + } + + @Provide + private func makeTodoGraphSet( + persistenceGraphSet: PersistenceGraphSet, + infraGraphSet: InfraGraphSet, + widgetGraphSet: WidgetGraphSet, + developmentGraphSet: DevelopmentGraphSet + ) -> TodoGraphSet { + TodoGraphSet( + todoQueryServiceGraph: infraGraphSet.todoQueryServiceGraph, + todoCommandServiceGraph: infraGraphSet.todoCommandServiceGraph, + todoCategoryServiceGraph: infraGraphSet.todoCategoryServiceGraph, + memoryCacheStoreGraph: persistenceGraphSet.memoryCacheStoreGraph, + widgetSnapshotUpdaterGraph: widgetGraphSet.widgetSnapshotUpdaterGraph, + developmentGoalRepositoryGraph: developmentGraphSet.developmentGoalRepositoryGraph + ) + } + + @Provide + private func makeWebPageGraphSet( + persistenceGraphSet: PersistenceGraphSet, + infraGraphSet: InfraGraphSet + ) -> WebPageGraphSet { + WebPageGraphSet( + authServiceGraph: infraGraphSet.authServiceGraph, + webPageMetadataServiceGraph: infraGraphSet.webPageMetadataServiceGraph, + webPageServiceGraph: infraGraphSet.webPageServiceGraph, + webPageImageStoreGraph: persistenceGraphSet.webPageImageStoreGraph + ) + } + + @Provide + private func makeUserProfileGraphSet( + persistenceGraphSet: PersistenceGraphSet, + infraGraphSet: InfraGraphSet + ) -> UserProfileGraphSet { + UserProfileGraphSet( + userServiceGraph: infraGraphSet.userServiceGraph, + profileImageDataServiceGraph: infraGraphSet.profileImageDataServiceGraph, + memoryCacheStoreGraph: persistenceGraphSet.memoryCacheStoreGraph + ) + } + + @Provide + private func makePushNotificationGraphSet( + persistenceGraphSet: PersistenceGraphSet, + infraGraphSet: InfraGraphSet + ) -> PushNotificationGraphSet { + PushNotificationGraphSet( + pushNotificationServiceGraph: infraGraphSet.pushNotificationServiceGraph, + todoCategoryServiceGraph: infraGraphSet.todoCategoryServiceGraph, + memoryCacheStoreGraph: persistenceGraphSet.memoryCacheStoreGraph + ) + } + + @Provide + private func makeUserPreferencesGraphSet( + persistenceGraphSet: PersistenceGraphSet, + widgetGraphSet: WidgetGraphSet + ) -> UserPreferencesGraphSet { + UserPreferencesGraphSet( + userDefaultsStoreGraph: persistenceGraphSet.userDefaultsStoreGraph, + themeStoreGraph: persistenceGraphSet.themeStoreGraph, + widgetSnapshotPreferenceStoreGraph: widgetGraphSet.widgetSnapshotPreferenceStoreGraph, + widgetSyncEventBusGraph: widgetGraphSet.widgetSyncEventBusGraph + ) + } + + @Provide + private func makeAnalyticsGraphSet( + infraGraphSet: InfraGraphSet + ) -> AnalyticsGraphSet { + AnalyticsGraphSet( + analyticsServiceGraph: infraGraphSet.analyticsServiceGraph + ) + } + + @Provide + private func makeAppUpdateGraphSet( + infraGraphSet: InfraGraphSet + ) -> AppUpdateGraphSet { + AppUpdateGraphSet( + appStoreVersionServiceGraph: infraGraphSet.appStoreVersionServiceGraph + ) + } + + @Provide + private func makeNetworkConnectivityGraphSet( + infraGraphSet: InfraGraphSet + ) -> NetworkConnectivityGraphSet { + NetworkConnectivityGraphSet( + networkConnectivityProviderGraph: infraGraphSet.networkConnectivityProviderGraph + ) + } +} From f19a4eb0b63e3e8ea462716a45b9539970f87323 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 16:18:51 +0900 Subject: [PATCH 14/19] =?UTF-8?q?docs:=20ai=20role=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/roles.md | 16 ++++++++-------- .agents/workflows.md | 12 ++++++------ .codex/agents/code_reviewer.toml | 4 ++-- .codex/agents/designer.toml | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.agents/roles.md b/.agents/roles.md index b8839fd9..400da41c 100644 --- a/.agents/roles.md +++ b/.agents/roles.md @@ -29,7 +29,7 @@ Use these model tiers when assigning work to another LLM. | Tier | Use | Default model | | --- | --- | --- | | `Primary` | Planning, implementation, architecture decisions, final integration, failed-check triage | Strongest available Codex/GPT coding model | -| `SDD Gate` | Design analysis and final diff review | `gpt-5.6-sol` with `xhigh` reasoning | +| `SDD Gate` | Design analysis and final diff review | `gpt-6-astra` with `medium` reasoning | | `Lightweight` | Read-only review, checklist validation, log summarization, documentation draft, first-pass architecture preflight | `gpt-5.3-codex-spark`, unavailable 시 `gpt-5.6-luna`와 `high` 추론 | | `Fast` | Low-risk text cleanup, simple file presence checks, short summaries | Pinned fast model from the configured custom agent TOML when a Fast role is defined | @@ -46,7 +46,7 @@ Default role-to-model and execution assignment: | GitHub/CI Analyst | `github_ci_analyst` | `Lightweight` | CI root cause requires code or workflow changes, or review comments conflict | | Documentation Writer | `documentation_writer` | `Lightweight` | Text must explain complex architecture, release risk, CI root cause, or PR scope tradeoffs | -Project-scoped custom agents live in `.codex/agents/`. Their TOML files pin the concrete model and sandbox for spawned sessions; this table is the canonical role-to-agent routing map. `Designer` and `Code Reviewer` are Sol-only SDD gates; the other custom roles retain the existing Spark-first routing. +Project-scoped custom agents live in `.codex/agents/`. Their TOML files pin the concrete model and sandbox for spawned sessions; this table is the canonical role-to-agent routing map. `Designer` and `Code Reviewer` are Astra-only SDD gates; the other custom roles retain the existing Spark-first routing. Do not assign `Lightweight` as the only model for production Swift implementation, target dependency changes, DI assembly, repository/service contract changes, Firebase or SDK placement, Widget data-flow changes, StorePattern responsibility changes, commits, pushes, PR creation, or final integration. @@ -54,13 +54,13 @@ Do not assign `Lightweight` as the only model for production Swift implementatio - A model tier assignment is an execution requirement, not a label for work the main agent already performed. - `Primary` roles belong to the active main agent and must not be delegated to a sub-agent that uses or inherits the active `Primary` model. -- Every sub-agent created through this role workflow must use the configured `SDD Gate`, `Lightweight`, or `Fast` model that is different from the active `Primary` model. The exact `designer` and `code_reviewer` custom agent dispatches are the only exception when the active `Primary` also uses their required Sol model. +- Every sub-agent created through this role workflow must use the configured `SDD Gate`, `Lightweight`, or `Fast` model that is different from the active `Primary` model. The exact `designer` and `code_reviewer` custom agent dispatches are the only exception when the active `Primary` also uses their required Astra model. - When a role is assigned to `SDD Gate`, `Lightweight`, or `Fast`, the main agent must dispatch the configured custom agent from the routing table before using its result. -- A sub-agent that inherits the active `Primary` model does not satisfy an `SDD Gate`, `Lightweight`, or `Fast` assignment. The Sol exception applies only to the exact `designer` and `code_reviewer` custom agent dispatches; it does not permit an inherited or generic sub-agent. +- A sub-agent that inherits the active `Primary` model does not satisfy an `SDD Gate`, `Lightweight`, or `Fast` assignment. The Astra exception applies only to the exact `designer` and `code_reviewer` custom agent dispatches; it does not permit an inherited or generic sub-agent. - Do not satisfy an `SDD Gate`, `Lightweight`, or `Fast` role by completing the role directly in `Primary` and describing it as delegated work. - A generic sub-agent spawn that does not load the configured custom agent TOML does not satisfy an `SDD Gate`, `Lightweight`, or `Fast` role execution. - If the custom agent cannot be loaded or the dispatch surface cannot select that custom agent, stop before dispatch and report which role cannot run. -- `Designer` and `Code Reviewer` must use only `gpt-5.6-sol` with `xhigh` reasoning. If the connected side-task surface cannot select Sol after an exact `task_name` retry, stop the SDD gate; do not use a fallback. +- `Designer` and `Code Reviewer` must use only `gpt-6-astra` with `medium` reasoning. If the connected side-task surface cannot select Astra after an exact `task_name` retry, stop the SDD gate; do not use a fallback. - A configured `gpt-5.3-codex-spark` model is unavailable only when the connected side-task surface cannot select it after an exact `task_name` retry. In that case, dispatch the matching `*_luna` custom role with `gpt-5.6-luna` and `high` reasoning effort. Do not select another fallback model. - If the assigned model is available but current tool policy requires explicit user permission before dispatch, missing permission is not fallback. Stop and ask for permission before continuing the required role. - `Primary` must integrate and verify delegated output, but must not skip the delegated role when the workflow requires it and the assigned model is available. @@ -233,7 +233,7 @@ Output: ## Designer -Designer is the `gpt-5.6-sol` and `xhigh` SDD gate for non-trivial work. +Designer is the `gpt-6-astra` and `medium` SDD gate for non-trivial work. May: @@ -245,7 +245,7 @@ Must not: - Edit files, stage changes, commit, push, or change GitHub state. - Approve its own result on behalf of the user. -- Select a fallback model when Sol is unavailable. +- Select a fallback model when Astra is unavailable. Output: @@ -344,7 +344,7 @@ Output: ## Code Reviewer -Code Reviewer is the `gpt-5.6-sol` and `xhigh` read-only final-diff SDD gate. +Code Reviewer is the `gpt-6-astra` and `medium` read-only final-diff SDD gate. May: diff --git a/.agents/workflows.md b/.agents/workflows.md index 95cd5ceb..1680983a 100644 --- a/.agents/workflows.md +++ b/.agents/workflows.md @@ -335,11 +335,11 @@ test -f .codex/agents/designer.toml test ! -e .codex/agents/designer_luna.toml test ! -e .codex/agents/code_reviewer_luna.toml rg -qx 'name = "designer"' .codex/agents/designer.toml -rg -qx 'model = "gpt-5.6-sol"' .codex/agents/designer.toml -rg -qx 'model_reasoning_effort = "xhigh"' .codex/agents/designer.toml +rg -qx 'model = "gpt-6-astra"' .codex/agents/designer.toml +rg -qx 'model_reasoning_effort = "medium"' .codex/agents/designer.toml rg -qx 'name = "code_reviewer"' .codex/agents/code_reviewer.toml -rg -qx 'model = "gpt-5.6-sol"' .codex/agents/code_reviewer.toml -rg -qx 'model_reasoning_effort = "xhigh"' .codex/agents/code_reviewer.toml +rg -qx 'model = "gpt-6-astra"' .codex/agents/code_reviewer.toml +rg -qx 'model_reasoning_effort = "medium"' .codex/agents/code_reviewer.toml ``` If only Markdown workflow files and agent TOML files changed, no iOS build is required. @@ -409,7 +409,7 @@ Include the selected workflow name in the task packet `Source` or `Goal` field s - Current owner: repository workflow documentation - Architecture risk: none - Required roles: Planner, Designer, Implementer, Code Reviewer, Verification Runner -- Model assignment: Planner=Primary, Designer=designer (SDD Gate, `gpt-5.6-sol`, `xhigh`), Implementer=Primary, Code Reviewer=code_reviewer (SDD Gate, `gpt-5.6-sol`, `xhigh`), Verification Runner=verification_runner (Lightweight) +- Model assignment: Planner=Primary, Designer=designer (SDD Gate, `gpt-6-astra`, `medium`), Implementer=Primary, Code Reviewer=code_reviewer (SDD Gate, `gpt-6-astra`, `medium`), Verification Runner=verification_runner (Lightweight) - Custom agent `task_name`: Designer=`designer`, Code Reviewer=`code_reviewer`, Verification Runner=`verification_runner` - Result recipient: `Primary` of the current main task - Execution authority: app or Simulator=not allowed / external writes=not allowed / CI or PR actions=not allowed @@ -432,7 +432,7 @@ Include the selected workflow name in the task packet `Source` or `Goal` field s - Current owner: - Architecture risk: none / possible / confirmed - Required roles: GitHub/CI Analyst, Planner, Designer, Implementer, Code Reviewer, Verification Runner -- Model assignment: GitHub/CI Analyst=github_ci_analyst (Lightweight), Planner=Primary, Designer=designer (SDD Gate, `gpt-5.6-sol`, `xhigh`), Implementer=Primary, Code Reviewer=code_reviewer (SDD Gate, `gpt-5.6-sol`, `xhigh`), Verification Runner=verification_runner (Lightweight) +- Model assignment: GitHub/CI Analyst=github_ci_analyst (Lightweight), Planner=Primary, Designer=designer (SDD Gate, `gpt-6-astra`, `medium`), Implementer=Primary, Code Reviewer=code_reviewer (SDD Gate, `gpt-6-astra`, `medium`), Verification Runner=verification_runner (Lightweight) - Custom agent `task_name`: GitHub/CI Analyst=`github_ci_analyst`, Designer=`designer`, Code Reviewer=`code_reviewer`, Verification Runner=`verification_runner` - Result recipient: `Primary` of the current main task - Execution authority: app or Simulator=not allowed / external writes=only user-authorized reply or resolution / CI or PR actions=inspection only diff --git a/.codex/agents/code_reviewer.toml b/.codex/agents/code_reviewer.toml index 786a200e..c6355a69 100644 --- a/.codex/agents/code_reviewer.toml +++ b/.codex/agents/code_reviewer.toml @@ -1,7 +1,7 @@ name = "code_reviewer" description = "Read-only DevLog code reviewer focused on correctness, regressions, scope drift, and missing verification." -model = "gpt-5.6-sol" -model_reasoning_effort = "xhigh" +model = "gpt-6-astra" +model_reasoning_effort = "medium" sandbox_mode = "read-only" developer_instructions = """ Read AGENTS.md and .agents/roles.md before reviewing. diff --git a/.codex/agents/designer.toml b/.codex/agents/designer.toml index 6579b3dc..ce0b8c28 100644 --- a/.codex/agents/designer.toml +++ b/.codex/agents/designer.toml @@ -1,7 +1,7 @@ name = "designer" description = "Read-only DevLog SDD gate for Design Brief analysis, Spec acceptance criteria, verification, and minimum commit units." -model = "gpt-5.6-sol" -model_reasoning_effort = "xhigh" +model = "gpt-6-astra" +model_reasoning_effort = "medium" sandbox_mode = "read-only" developer_instructions = """ Read AGENTS.md and .agents/roles.md before analysis. From f5d6ff8f2ac7dd64569032dabecb681f740cfe43 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 17:03:58 +0900 Subject: [PATCH 15/19] =?UTF-8?q?refactor:=20Presentation=20TCA=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A4=80=EB=B9=84=20=EA=B2=BD?= =?UTF-8?q?=EA=B3=84=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PresentationDependencyPreparation.swift | 47 +++++++++++ .../Home/HomeDependencyPreparation.swift | 79 +++++++++++++++++ ...ushNotificationDependencyPreparation.swift | 51 +++++++++++ .../TodoDependencyPreparation.swift | 56 +++++++++++++ .../ProfileDependencyPreparation.swift | 84 +++++++++++++++++++ .../Today/TodayDependencyPreparation.swift | 35 ++++++++ 6 files changed, 352 insertions(+) create mode 100644 Application/Presentation/Entry/Sources/Dependency/PresentationDependencyPreparation.swift create mode 100644 Application/Presentation/HomeTab/Sources/Home/HomeDependencyPreparation.swift create mode 100644 Application/Presentation/NotificationTab/Sources/PushNotificationDependencyPreparation.swift create mode 100644 Application/Presentation/PresentationShared/Sources/Dependency/TodoDependencyPreparation.swift create mode 100644 Application/Presentation/ProfileTab/Sources/Profile/ProfileDependencyPreparation.swift create mode 100644 Application/Presentation/TodayTab/Sources/Today/TodayDependencyPreparation.swift diff --git a/Application/Presentation/Entry/Sources/Dependency/PresentationDependencyPreparation.swift b/Application/Presentation/Entry/Sources/Dependency/PresentationDependencyPreparation.swift new file mode 100644 index 00000000..cc787b6e --- /dev/null +++ b/Application/Presentation/Entry/Sources/Dependency/PresentationDependencyPreparation.swift @@ -0,0 +1,47 @@ +// +// PresentationDependencyPreparation.swift +// Entry +// +// Created by opfic on 9/7/26. +// + +import Domain +import HomeTab +import NotificationTab +import PresentationShared +import ProfileTab +import TodayTab + +public enum PresentationDependencyPreparation { + public static func prepareRoot( + _ dependencies: inout DependencyValues, + sessionUseCase: ObserveAuthSessionUseCase, + networkConnectivityUseCase: ObserveNetworkConnectivityUseCase, + systemThemeUseCase: ObserveSystemThemeUseCase, + checkAppUpdateUseCase: CheckAppUpdateUseCase + ) { + dependencies.observeAuthSessionUseCase = sessionUseCase + dependencies.rootNetworkConnectivityUseCase = networkConnectivityUseCase + dependencies.rootSystemThemeUseCase = systemThemeUseCase + dependencies.checkAppUpdateUseCase = checkAppUpdateUseCase + } + + public static func prepareLogin( + _ dependencies: inout DependencyValues, + signInUseCase: SignInUseCase + ) { + dependencies.signInUseCase = signInUseCase + } + + public static func prepareMain( + _ dependencies: inout DependencyValues, + observeUnreadPushCountUseCase: ObserveUnreadPushCountUseCase + ) { + dependencies.observeUnreadPushCountUseCase = observeUnreadPushCountUseCase + } +} + +public typealias HomePresentationDependencyPreparation = HomeDependencyPreparation +public typealias NotificationDependencyPreparation = PushNotificationDependencyPreparation +public typealias ProfilePresentationDependencyPreparation = ProfileDependencyPreparation +public typealias TodayPresentationDependencyPreparation = TodayDependencyPreparation diff --git a/Application/Presentation/HomeTab/Sources/Home/HomeDependencyPreparation.swift b/Application/Presentation/HomeTab/Sources/Home/HomeDependencyPreparation.swift new file mode 100644 index 00000000..15cf5718 --- /dev/null +++ b/Application/Presentation/HomeTab/Sources/Home/HomeDependencyPreparation.swift @@ -0,0 +1,79 @@ +// +// HomeDependencyPreparation.swift +// HomeTab +// +// Created by opfic on 9/7/26. +// + +import Domain +import PresentationShared + +public enum HomeDependencyPreparation { + public static func prepareTodoCategory( + _ dependencies: inout DependencyValues, + updateTodoCategoryPreferencesUseCase: UpdateTodoCategoryPreferencesUseCase, + todoMutationEventBus: TodoMutationEventBus + ) { + dependencies.homeUpdateTodoCategoryPreferencesUseCase = updateTodoCategoryPreferencesUseCase + dependencies.homeTodoMutationEventBus = todoMutationEventBus + } + + public static func prepareWebPage( + _ dependencies: inout DependencyValues, + addWebPageUseCase: AddWebPageUseCase, + deleteWebPageUseCase: DeleteWebPageUseCase, + undoDeleteWebPageUseCase: UndoDeleteWebPageUseCase, + fetchWebPagesUseCase: FetchWebPagesUseCase + ) { + dependencies.homeAddWebPageUseCase = addWebPageUseCase + dependencies.homeDeleteWebPageUseCase = deleteWebPageUseCase + dependencies.homeUndoDeleteWebPageUseCase = undoDeleteWebPageUseCase + dependencies.homeFetchWebPagesUseCase = fetchWebPagesUseCase + } + + public static func prepareTodo( + _ dependencies: inout DependencyValues, + fetchTodosUseCase: FetchTodosUseCase, + networkConnectivityUseCase: ObserveNetworkConnectivityUseCase + ) { + dependencies.homeFetchTodosUseCase = fetchTodosUseCase + dependencies.homeNetworkConnectivityUseCase = networkConnectivityUseCase + } + + public static func prepareSearch( + _ dependencies: inout DependencyValues, + fetchRecentSearchQueriesUseCase: FetchRecentSearchQueriesUseCase, + fetchTodosUseCase: FetchTodosUseCase, + fetchWebPagesUseCase: FetchWebPagesUseCase, + updateRecentSearchQueriesUseCase: UpdateRecentSearchQueriesUseCase + ) { + dependencies.homeFetchRecentSearchQueriesUseCase = fetchRecentSearchQueriesUseCase + dependencies.searchFetchTodosUseCase = fetchTodosUseCase + dependencies.searchFetchWebPagesUseCase = fetchWebPagesUseCase + dependencies.searchUpdateRecentQueriesUseCase = updateRecentSearchQueriesUseCase + } +} + +extension DependencyValues { + var homeTodoMutationEventBus: TodoMutationEventBus { + get { self[HomeTodoMutationEventBusKey.self] } + set { self[HomeTodoMutationEventBusKey.self] = newValue } + } + + var homeFetchRecentSearchQueriesUseCase: FetchRecentSearchQueriesUseCase { + get { self[HomeFetchRecentSearchQueriesUseCaseKey.self] } + set { self[HomeFetchRecentSearchQueriesUseCaseKey.self] = newValue } + } +} + +private enum HomeTodoMutationEventBusKey: DependencyKey { + static var liveValue: TodoMutationEventBus { + preconditionFailure("TodoMutationEventBus must be provided.") + } +} + +private enum HomeFetchRecentSearchQueriesUseCaseKey: DependencyKey { + static var liveValue: FetchRecentSearchQueriesUseCase { + preconditionFailure("FetchRecentSearchQueriesUseCase must be provided.") + } +} diff --git a/Application/Presentation/NotificationTab/Sources/PushNotificationDependencyPreparation.swift b/Application/Presentation/NotificationTab/Sources/PushNotificationDependencyPreparation.swift new file mode 100644 index 00000000..5dab9f2f --- /dev/null +++ b/Application/Presentation/NotificationTab/Sources/PushNotificationDependencyPreparation.swift @@ -0,0 +1,51 @@ +// +// PushNotificationDependencyPreparation.swift +// NotificationTab +// +// Created by opfic on 9/7/26. +// + +import Domain +import PresentationShared + +public enum PushNotificationDependencyPreparation { + public static func prepareQuery( + _ dependencies: inout DependencyValues, + fetchQueryUseCase: FetchPushNotificationQueryUseCase, + updateQueryUseCase: UpdatePushNotificationQueryUseCase + ) { + dependencies.fetchPushNotificationQueryUseCase = fetchQueryUseCase + dependencies.updatePushNotificationQueryUseCase = updateQueryUseCase + } + + public static func prepareList( + _ dependencies: inout DependencyValues, + fetchNotificationsUseCase: FetchPushNotificationsUseCase, + deleteNotificationUseCase: DeletePushNotificationUseCase, + undoDeleteNotificationUseCase: UndoDeletePushNotificationUseCase + ) { + dependencies.fetchPushNotificationsUseCase = fetchNotificationsUseCase + dependencies.deletePushNotificationUseCase = deleteNotificationUseCase + dependencies.undoDeletePushNotificationUseCase = undoDeleteNotificationUseCase + } + + public static func prepareReadState( + _ dependencies: inout DependencyValues, + toggleNotificationReadUseCase: TogglePushNotificationReadUseCase + ) { + dependencies.togglePushNotificationReadUseCase = toggleNotificationReadUseCase + } +} + +extension DependencyValues { + var fetchPushNotificationQueryUseCase: FetchPushNotificationQueryUseCase { + get { self[FetchPushNotificationQueryUseCaseKey.self] } + set { self[FetchPushNotificationQueryUseCaseKey.self] = newValue } + } +} + +private enum FetchPushNotificationQueryUseCaseKey: DependencyKey { + static var liveValue: FetchPushNotificationQueryUseCase { + preconditionFailure("FetchPushNotificationQueryUseCase must be provided.") + } +} diff --git a/Application/Presentation/PresentationShared/Sources/Dependency/TodoDependencyPreparation.swift b/Application/Presentation/PresentationShared/Sources/Dependency/TodoDependencyPreparation.swift new file mode 100644 index 00000000..d315b634 --- /dev/null +++ b/Application/Presentation/PresentationShared/Sources/Dependency/TodoDependencyPreparation.swift @@ -0,0 +1,56 @@ +// +// TodoDependencyPreparation.swift +// PresentationShared +// +// Created by opfic on 9/7/26. +// + +import Domain + +public enum TodoDependencyPreparation { + public static func prepareDetail( + _ dependencies: inout DependencyValues, + fetchTodoByIdUseCase: FetchTodoByIdUseCase, + fetchReferenceItemsUseCase: FetchReferenceItemsUseCase + ) { + dependencies.fetchTodoByIdUseCase = fetchTodoByIdUseCase + dependencies.fetchReferenceItemsUseCase = fetchReferenceItemsUseCase + } + + public static func prepareEditor( + _ dependencies: inout DependencyValues, + fetchTodoCategoryPreferencesUseCase: FetchTodoCategoryPreferencesUseCase, + fetchReferenceItemsUseCase: FetchReferenceItemsUseCase, + upsertTodoUseCase: UpsertTodoUseCase + ) { + dependencies.fetchTodoCategoryPreferencesUseCase = fetchTodoCategoryPreferencesUseCase + dependencies.fetchReferenceItemsUseCase = fetchReferenceItemsUseCase + dependencies.upsertTodoUseCase = upsertTodoUseCase + } + + public static func prepareListQuery( + _ dependencies: inout DependencyValues, + fetchTodosUseCase: FetchTodosUseCase, + fetchTodoByIdUseCase: FetchTodoByIdUseCase, + fetchReferenceItemsUseCase: FetchReferenceItemsUseCase, + fetchTodoCategoryPreferencesUseCase: FetchTodoCategoryPreferencesUseCase + ) { + dependencies.todoListFetchTodosUseCase = fetchTodosUseCase + dependencies.fetchTodoByIdUseCase = fetchTodoByIdUseCase + dependencies.fetchReferenceItemsUseCase = fetchReferenceItemsUseCase + dependencies.fetchTodoCategoryPreferencesUseCase = fetchTodoCategoryPreferencesUseCase + } + + public static func prepareListMutation( + _ dependencies: inout DependencyValues, + upsertTodoUseCase: UpsertTodoUseCase, + deleteTodoUseCase: DeleteTodoUseCase, + undoDeleteTodoUseCase: UndoDeleteTodoUseCase, + trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase + ) { + dependencies.upsertTodoUseCase = upsertTodoUseCase + dependencies.todoListDeleteTodoUseCase = deleteTodoUseCase + dependencies.todoListUndoDeleteTodoUseCase = undoDeleteTodoUseCase + dependencies.trackAnalyticsEventUseCase = trackAnalyticsEventUseCase + } +} diff --git a/Application/Presentation/ProfileTab/Sources/Profile/ProfileDependencyPreparation.swift b/Application/Presentation/ProfileTab/Sources/Profile/ProfileDependencyPreparation.swift new file mode 100644 index 00000000..adde2d64 --- /dev/null +++ b/Application/Presentation/ProfileTab/Sources/Profile/ProfileDependencyPreparation.swift @@ -0,0 +1,84 @@ +// +// ProfileDependencyPreparation.swift +// ProfileTab +// +// Created by opfic on 9/7/26. +// + +import Domain +import PresentationShared + +public enum ProfileDependencyPreparation { + public static func prepareUser( + _ dependencies: inout DependencyValues, + fetchUserDataUseCase: FetchUserDataUseCase, + fetchProfileImageDataUseCase: FetchProfileImageDataUseCase, + upsertStatusMessageUseCase: UpsertStatusMessageUseCase + ) { + dependencies.profileFetchUserDataUseCase = fetchUserDataUseCase + dependencies.profileFetchImageDataUseCase = fetchProfileImageDataUseCase + dependencies.profileUpsertStatusMessageUseCase = upsertStatusMessageUseCase + } + + public static func prepareActivity( + _ dependencies: inout DependencyValues, + fetchTodosUseCase: FetchTodosUseCase, + networkConnectivityUseCase: ObserveNetworkConnectivityUseCase, + fetchHeatmapActivityTypesUseCase: FetchHeatmapActivityTypesUseCase, + updateHeatmapActivityTypesUseCase: UpdateHeatmapActivityTypesUseCase + ) { + dependencies.profileFetchTodosUseCase = fetchTodosUseCase + dependencies.profileNetworkConnectivityUseCase = networkConnectivityUseCase + dependencies.profileFetchHeatmapActivityTypesUseCase = fetchHeatmapActivityTypesUseCase + dependencies.profileUpdateHeatmapActivityTypesUseCase = updateHeatmapActivityTypesUseCase + } + + public static func prepareSettingsSession( + _ dependencies: inout DependencyValues, + deleteAuthUseCase: DeleteAuthUseCase, + signOutUseCase: SignOutUseCase, + networkConnectivityUseCase: ObserveNetworkConnectivityUseCase + ) { + dependencies.deleteAuthUseCase = deleteAuthUseCase + dependencies.signOutUseCase = signOutUseCase + dependencies.profileNetworkConnectivityUseCase = networkConnectivityUseCase + } + + public static func prepareSettingsAppearance( + _ dependencies: inout DependencyValues, + systemThemeUseCase: ObserveSystemThemeUseCase, + updateSystemThemeUseCase: UpdateSystemThemeUseCase + ) { + dependencies.profileSystemThemeUseCase = systemThemeUseCase + dependencies.updateSystemThemeUseCase = updateSystemThemeUseCase + } + + public static func prepareSettingsStorage( + _ dependencies: inout DependencyValues, + fetchWebPageImageDirSizeUseCase: FetchWebPageImageDirSizeUseCase, + clearWebPageImageDirectoryUseCase: ClearWebPageImageDirectoryUseCase + ) { + dependencies.fetchWebPageImageDirSizeUseCase = fetchWebPageImageDirSizeUseCase + dependencies.clearWebPageImageDirectoryUseCase = clearWebPageImageDirectoryUseCase + } + + public static func prepareAccount( + _ dependencies: inout DependencyValues, + fetchAuthProvidersUseCase: FetchAuthProvidersUseCase, + linkAuthProviderUseCase: LinkAuthProviderUseCase, + unlinkAuthProviderUseCase: UnlinkAuthProviderUseCase + ) { + dependencies.fetchAuthProvidersUseCase = fetchAuthProvidersUseCase + dependencies.linkAuthProviderUseCase = linkAuthProviderUseCase + dependencies.unlinkAuthProviderUseCase = unlinkAuthProviderUseCase + } + + public static func preparePushSettings( + _ dependencies: inout DependencyValues, + fetchPushSettingsUseCase: FetchPushSettingsUseCase, + updatePushSettingsUseCase: UpdatePushSettingsUseCase + ) { + dependencies.fetchPushSettingsUseCase = fetchPushSettingsUseCase + dependencies.updatePushSettingsUseCase = updatePushSettingsUseCase + } +} diff --git a/Application/Presentation/TodayTab/Sources/Today/TodayDependencyPreparation.swift b/Application/Presentation/TodayTab/Sources/Today/TodayDependencyPreparation.swift new file mode 100644 index 00000000..cc76e25c --- /dev/null +++ b/Application/Presentation/TodayTab/Sources/Today/TodayDependencyPreparation.swift @@ -0,0 +1,35 @@ +// +// TodayDependencyPreparation.swift +// TodayTab +// +// Created by opfic on 9/7/26. +// + +import Domain +import PresentationShared + +public enum TodayDependencyPreparation { + public static func prepare( + _ dependencies: inout DependencyValues, + fetchDisplayOptionsUseCase: FetchTodayDisplayOptionsUseCase, + fetchTodosUseCase: FetchTodosUseCase, + updateDisplayOptionsUseCase: UpdateTodayDisplayOptionsUseCase + ) { + dependencies.todayFetchDisplayOptionsUseCase = fetchDisplayOptionsUseCase + dependencies.todayFetchTodosUseCase = fetchTodosUseCase + dependencies.updateTodayDisplayOptionsUseCase = updateDisplayOptionsUseCase + } +} + +extension DependencyValues { + var todayFetchDisplayOptionsUseCase: FetchTodayDisplayOptionsUseCase { + get { self[TodayFetchDisplayOptionsUseCaseKey.self] } + set { self[TodayFetchDisplayOptionsUseCaseKey.self] = newValue } + } +} + +private enum TodayFetchDisplayOptionsUseCaseKey: DependencyKey { + static var liveValue: FetchTodayDisplayOptionsUseCase { + preconditionFailure("FetchTodayDisplayOptionsUseCase must be provided.") + } +} From 4f8849d174d17b682402367cb981078d4264d9a7 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 17:04:30 +0900 Subject: [PATCH 16/19] =?UTF-8?q?refactor:=20App=20lifecycle=20handler=20g?= =?UTF-8?q?raph=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/App/Delegate/AppDelegate.swift | 20 +++--- .../App/Sources/App/Graph/AppGraph.swift | 18 ++++++ .../App/Graph/FCMTokenSyncHandlerGraph.swift | 27 ++++++++ .../Sources/App/Graph/LifecycleGraphSet.swift | 61 +++++++++++++++++++ .../PushNotificationOpenHandlerGraph.swift | 21 +++++++ .../Graph/UserTimeZoneSyncHandlerGraph.swift | 25 ++++++++ 6 files changed, 163 insertions(+), 9 deletions(-) create mode 100644 Application/App/Sources/App/Graph/FCMTokenSyncHandlerGraph.swift create mode 100644 Application/App/Sources/App/Graph/LifecycleGraphSet.swift create mode 100644 Application/App/Sources/App/Graph/PushNotificationOpenHandlerGraph.swift create mode 100644 Application/App/Sources/App/Graph/UserTimeZoneSyncHandlerGraph.swift diff --git a/Application/App/Sources/App/Delegate/AppDelegate.swift b/Application/App/Sources/App/Delegate/AppDelegate.swift index ca1daa5f..b4446bce 100644 --- a/Application/App/Sources/App/Delegate/AppDelegate.swift +++ b/Application/App/Sources/App/Delegate/AppDelegate.swift @@ -13,7 +13,6 @@ import Widget class AppDelegate: UIResponder, UIApplicationDelegate { private let logger = Logger(category: "AppDelegate") - private let container = AppDIContainer.shared // Google 로그인 URL 콜백 처리 func application( @@ -28,11 +27,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil ) -> Bool { - container.resolve(FirebaseAppService.self).configure() - _ = container.resolve(FCMTokenSyncHandler.self) - _ = container.resolve(UserTimeZoneSyncHandler.self) - _ = container.resolve(WidgetSyncEventHandler.self) - _ = container.resolve(WidgetSessionSyncHandler.self) + let lifecycleGraphSet = AppGraph.shared.lifecycleGraphSet + _ = lifecycleGraphSet.fcmTokenSyncHandlerGraph.fcmTokenSyncHandler + _ = lifecycleGraphSet.userTimeZoneSyncHandlerGraph.userTimeZoneSyncHandler + _ = lifecycleGraphSet.widgetSyncEventHandlerGraph.widgetSyncEventHandler + _ = lifecycleGraphSet.widgetSessionSyncHandlerGraph.widgetSessionSyncHandler NotificationCenter.default.addObserver( self, selector: #selector(handleRemoteNotificationRegistrationRequest), @@ -64,11 +63,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } // Firebase Messaging 설정 - container.resolve(PushMessagingService.self).setDelegate(self) + AppGraph.shared.infraGraphSet.pushMessagingServiceGraph.pushMessagingService.setDelegate(self) // 앱이 완전 종료되어도, 알림을 통해 앱이 시작된 경우 처리 if let remoteNotification = launchOptions?[.remoteNotification] as? [AnyHashable: Any] { - let handler = container.resolve(PushNotificationOpenHandler.self) + let handler = lifecycleGraphSet.pushNotificationOpenHandlerGraph.pushNotificationOpenHandler Task { @MainActor in handler.handlePushOpen(userInfo: remoteNotification) } @@ -145,7 +144,10 @@ extension AppDelegate: UNUserNotificationCenterDelegate { ) { logger.info("Tapped notification: \(response.notification.request.content.userInfo)") let userInfo = response.notification.request.content.userInfo - let handler = container.resolve(PushNotificationOpenHandler.self) + let handler = AppGraph.shared + .lifecycleGraphSet + .pushNotificationOpenHandlerGraph + .pushNotificationOpenHandler Task { @MainActor in handler.handlePushOpen(userInfo: userInfo) } diff --git a/Application/App/Sources/App/Graph/AppGraph.swift b/Application/App/Sources/App/Graph/AppGraph.swift index f76d7b8e..ee42be17 100644 --- a/Application/App/Sources/App/Graph/AppGraph.swift +++ b/Application/App/Sources/App/Graph/AppGraph.swift @@ -151,4 +151,22 @@ final class AppGraph { networkConnectivityProviderGraph: infraGraphSet.networkConnectivityProviderGraph ) } + + @Provide + private func makeLifecycleGraphSet( + infraGraphSet: InfraGraphSet, + widgetGraphSet: WidgetGraphSet, + todoGraphSet: TodoGraphSet + ) -> LifecycleGraphSet { + LifecycleGraphSet( + authServiceGraph: infraGraphSet.authServiceGraph, + pushMessagingServiceGraph: infraGraphSet.pushMessagingServiceGraph, + userServiceGraph: infraGraphSet.userServiceGraph, + analyticsServiceGraph: infraGraphSet.analyticsServiceGraph, + widgetSyncEventBusGraph: widgetGraphSet.widgetSyncEventBusGraph, + widgetTodoSnapshotRepositoryGraph: todoGraphSet.widgetTodoSnapshotRepositoryGraph, + widgetSnapshotUpdaterGraph: widgetGraphSet.widgetSnapshotUpdaterGraph, + authSessionStateProviderGraph: widgetGraphSet.authSessionStateProviderGraph + ) + } } diff --git a/Application/App/Sources/App/Graph/FCMTokenSyncHandlerGraph.swift b/Application/App/Sources/App/Graph/FCMTokenSyncHandlerGraph.swift new file mode 100644 index 00000000..286f440f --- /dev/null +++ b/Application/App/Sources/App/Graph/FCMTokenSyncHandlerGraph.swift @@ -0,0 +1,27 @@ +// +// FCMTokenSyncHandlerGraph.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +struct FCMTokenSyncHandlerGraphInput { + let authService: AuthService + let messagingService: PushMessagingService + let userService: UserService +} + +@DependencyGraph(input: FCMTokenSyncHandlerGraphInput.self) +final class FCMTokenSyncHandlerGraph { + @Provide(.lazy) + private func makeFCMTokenSyncHandler() -> FCMTokenSyncHandler { + FCMTokenSyncHandler( + authService: input.authService, + messagingService: input.messagingService, + userService: input.userService + ) + } +} diff --git a/Application/App/Sources/App/Graph/LifecycleGraphSet.swift b/Application/App/Sources/App/Graph/LifecycleGraphSet.swift new file mode 100644 index 00000000..f8f4ac83 --- /dev/null +++ b/Application/App/Sources/App/Graph/LifecycleGraphSet.swift @@ -0,0 +1,61 @@ +// +// LifecycleGraphSet.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Data +import Infra +import Widget + +final class LifecycleGraphSet { + let fcmTokenSyncHandlerGraph: FCMTokenSyncHandlerGraph + let userTimeZoneSyncHandlerGraph: UserTimeZoneSyncHandlerGraph + let widgetSyncEventHandlerGraph: WidgetSyncEventHandlerGraph + let widgetSessionSyncHandlerGraph: WidgetSessionSyncHandlerGraph + let pushNotificationOpenHandlerGraph: PushNotificationOpenHandlerGraph + + init( + authServiceGraph: AuthServiceGraph, + pushMessagingServiceGraph: PushMessagingServiceGraph, + userServiceGraph: UserServiceGraph, + analyticsServiceGraph: AnalyticsServiceGraph, + widgetSyncEventBusGraph: WidgetSyncEventBusGraph, + widgetTodoSnapshotRepositoryGraph: WidgetTodoSnapshotRepositoryGraph, + widgetSnapshotUpdaterGraph: WidgetSnapshotUpdaterGraph, + authSessionStateProviderGraph: AuthSessionStateProviderGraph + ) { + self.fcmTokenSyncHandlerGraph = FCMTokenSyncHandlerGraph( + input: FCMTokenSyncHandlerGraphInput( + authService: authServiceGraph.authService, + messagingService: pushMessagingServiceGraph.pushMessagingService, + userService: userServiceGraph.userService + ) + ) + self.userTimeZoneSyncHandlerGraph = UserTimeZoneSyncHandlerGraph( + input: UserTimeZoneSyncHandlerGraphInput( + authService: authServiceGraph.authService, + userService: userServiceGraph.userService + ) + ) + self.widgetSyncEventHandlerGraph = WidgetSyncEventHandlerGraph( + input: WidgetSyncEventHandlerGraphInput( + eventBus: widgetSyncEventBusGraph.widgetSyncEventBus, + repository: widgetTodoSnapshotRepositoryGraph.widgetTodoSnapshotRepository, + snapshotUpdater: widgetSnapshotUpdaterGraph.widgetSnapshotUpdater + ) + ) + self.widgetSessionSyncHandlerGraph = WidgetSessionSyncHandlerGraph( + input: WidgetSessionSyncHandlerGraphInput( + provider: authSessionStateProviderGraph.authSessionStateProvider, + widgetSyncEventBus: widgetSyncEventBusGraph.widgetSyncEventBus + ) + ) + self.pushNotificationOpenHandlerGraph = PushNotificationOpenHandlerGraph( + input: PushNotificationOpenHandlerGraphInput( + analyticsService: analyticsServiceGraph.analyticsService + ) + ) + } +} diff --git a/Application/App/Sources/App/Graph/PushNotificationOpenHandlerGraph.swift b/Application/App/Sources/App/Graph/PushNotificationOpenHandlerGraph.swift new file mode 100644 index 00000000..6bd4a02a --- /dev/null +++ b/Application/App/Sources/App/Graph/PushNotificationOpenHandlerGraph.swift @@ -0,0 +1,21 @@ +// +// PushNotificationOpenHandlerGraph.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +struct PushNotificationOpenHandlerGraphInput { + let analyticsService: AnalyticsService +} + +@DependencyGraph(input: PushNotificationOpenHandlerGraphInput.self) +final class PushNotificationOpenHandlerGraph { + @Provide(.lazy) + private func makePushNotificationOpenHandler() -> PushNotificationOpenHandler { + PushNotificationOpenHandler(analyticsService: input.analyticsService) + } +} diff --git a/Application/App/Sources/App/Graph/UserTimeZoneSyncHandlerGraph.swift b/Application/App/Sources/App/Graph/UserTimeZoneSyncHandlerGraph.swift new file mode 100644 index 00000000..9135de51 --- /dev/null +++ b/Application/App/Sources/App/Graph/UserTimeZoneSyncHandlerGraph.swift @@ -0,0 +1,25 @@ +// +// UserTimeZoneSyncHandlerGraph.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Cradle +import Data + +struct UserTimeZoneSyncHandlerGraphInput { + let authService: AuthService + let userService: UserService +} + +@DependencyGraph(input: UserTimeZoneSyncHandlerGraphInput.self) +final class UserTimeZoneSyncHandlerGraph { + @Provide(.lazy) + private func makeUserTimeZoneSyncHandler() -> UserTimeZoneSyncHandler { + UserTimeZoneSyncHandler( + authService: input.authService, + userService: input.userService + ) + } +} From b11198eae8bd9b19de81f5007190320c4471e9df Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 17:05:20 +0900 Subject: [PATCH 17/19] =?UTF-8?q?refactor:=20App=EA=B3=BC=20Presentation?= =?UTF-8?q?=20Cradle=20graph=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppGraph+PresentationDependencies.swift | 232 ++++++++++++++++++ Application/App/Sources/App/DevLogApp.swift | 17 +- .../Entry/Sources/Login/LoginView.swift | 4 +- .../Entry/Sources/Main/MainView.swift | 16 +- .../Entry/Sources/Root/RootView.swift | 20 +- .../WindowGroup/TodoEditorWindowView.swift | 14 -- .../WindowGroup/TodoWindowCoordinator.swift | 24 +- .../Home/Home/HomeViewCoordinator.swift | 32 +-- .../Sources/Home/Search/SearchView.swift | 9 - .../PushNotificationListViewCoordinator.swift | 18 +- .../Detail/TodoDetailPreviewModifier.swift | 5 - .../Sources/Todo/Detail/TodoDetailView.swift | 1 - .../Sources/Todo/Editor/TodoEditorView.swift | 4 - .../Profile/ProfileViewCoordinator.swift | 31 +-- .../Sources/Today/TodayViewCoordinator.swift | 11 +- 15 files changed, 260 insertions(+), 178 deletions(-) create mode 100644 Application/App/Sources/App/Dependency/AppGraph+PresentationDependencies.swift diff --git a/Application/App/Sources/App/Dependency/AppGraph+PresentationDependencies.swift b/Application/App/Sources/App/Dependency/AppGraph+PresentationDependencies.swift new file mode 100644 index 00000000..c358cb2f --- /dev/null +++ b/Application/App/Sources/App/Dependency/AppGraph+PresentationDependencies.swift @@ -0,0 +1,232 @@ +// +// AppGraph+PresentationDependencies.swift +// App +// +// Created by opfic on 9/7/26. +// + +import Presentation + +extension AppGraph { + func preparePresentationDependencies() { + prepareDependencies { dependencies in + prepareEntryDependencies(&dependencies) + prepareTodoDependencies(&dependencies) + prepareHomeDependencies(&dependencies) + prepareTodayDependencies(&dependencies) + prepareNotificationDependencies(&dependencies) + prepareProfileDependencies(&dependencies) + } + } +} + +private extension AppGraph { + func prepareEntryDependencies(_ dependencies: inout DependencyValues) { + PresentationDependencyPreparation.prepareRoot( + &dependencies, + sessionUseCase: authenticationGraphSet.authSessionUseCaseGraph.observeAuthSessionUseCase, + networkConnectivityUseCase: networkConnectivityGraphSet + .networkConnectivityUseCaseGraph + .observeNetworkConnectivityUseCase, + systemThemeUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .observeSystemThemeUseCase, + checkAppUpdateUseCase: appUpdateGraphSet.appUpdateUseCaseGraph.checkAppUpdateUseCase + ) + PresentationDependencyPreparation.prepareLogin( + &dependencies, + signInUseCase: authenticationGraphSet.authenticationUseCaseGraph.signInUseCase + ) + PresentationDependencyPreparation.prepareMain( + &dependencies, + observeUnreadPushCountUseCase: pushNotificationGraphSet + .pushNotificationUseCaseGraph + .observeUnreadPushCountUseCase + ) + } + + func prepareTodoDependencies(_ dependencies: inout DependencyValues) { + TodoDependencyPreparation.prepareDetail( + &dependencies, + fetchTodoByIdUseCase: todoGraphSet.todoUseCaseGraph.fetchTodoByIdUseCase, + fetchReferenceItemsUseCase: todoGraphSet.todoUseCaseGraph.fetchReferenceItemsUseCase + ) + TodoDependencyPreparation.prepareEditor( + &dependencies, + fetchTodoCategoryPreferencesUseCase: todoGraphSet + .todoCategoryUseCaseGraph + .fetchTodoCategoryPreferencesUseCase, + fetchReferenceItemsUseCase: todoGraphSet.todoUseCaseGraph.fetchReferenceItemsUseCase, + upsertTodoUseCase: todoGraphSet.todoUseCaseGraph.upsertTodoUseCase + ) + TodoDependencyPreparation.prepareListQuery( + &dependencies, + fetchTodosUseCase: todoGraphSet.todoUseCaseGraph.fetchTodosUseCase, + fetchTodoByIdUseCase: todoGraphSet.todoUseCaseGraph.fetchTodoByIdUseCase, + fetchReferenceItemsUseCase: todoGraphSet.todoUseCaseGraph.fetchReferenceItemsUseCase, + fetchTodoCategoryPreferencesUseCase: todoGraphSet + .todoCategoryUseCaseGraph + .fetchTodoCategoryPreferencesUseCase + ) + TodoDependencyPreparation.prepareListMutation( + &dependencies, + upsertTodoUseCase: todoGraphSet.todoUseCaseGraph.upsertTodoUseCase, + deleteTodoUseCase: todoGraphSet.todoUseCaseGraph.deleteTodoUseCase, + undoDeleteTodoUseCase: todoGraphSet.todoUseCaseGraph.undoDeleteTodoUseCase, + trackAnalyticsEventUseCase: analyticsGraphSet + .analyticsUseCaseGraph + .trackAnalyticsEventUseCase + ) + } + + func prepareHomeDependencies(_ dependencies: inout DependencyValues) { + HomePresentationDependencyPreparation.prepareTodoCategory( + &dependencies, + updateTodoCategoryPreferencesUseCase: todoGraphSet + .todoCategoryUseCaseGraph + .updateTodoCategoryPreferencesUseCase, + todoMutationEventBus: todoGraphSet.todoMutationEventBusGraph.todoMutationEventBus + ) + HomePresentationDependencyPreparation.prepareWebPage( + &dependencies, + addWebPageUseCase: webPageGraphSet.webPageUseCaseGraph.addWebPageUseCase, + deleteWebPageUseCase: webPageGraphSet.webPageUseCaseGraph.deleteWebPageUseCase, + undoDeleteWebPageUseCase: webPageGraphSet.webPageUseCaseGraph.undoDeleteWebPageUseCase, + fetchWebPagesUseCase: webPageGraphSet.webPageUseCaseGraph.fetchWebPagesUseCase + ) + HomePresentationDependencyPreparation.prepareTodo( + &dependencies, + fetchTodosUseCase: todoGraphSet.todoUseCaseGraph.fetchTodosUseCase, + networkConnectivityUseCase: networkConnectivityGraphSet + .networkConnectivityUseCaseGraph + .observeNetworkConnectivityUseCase + ) + HomePresentationDependencyPreparation.prepareSearch( + &dependencies, + fetchRecentSearchQueriesUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .fetchRecentSearchQueriesUseCase, + fetchTodosUseCase: todoGraphSet.todoUseCaseGraph.fetchTodosUseCase, + fetchWebPagesUseCase: webPageGraphSet.webPageUseCaseGraph.fetchWebPagesUseCase, + updateRecentSearchQueriesUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .updateRecentSearchQueriesUseCase + ) + } + + func prepareTodayDependencies(_ dependencies: inout DependencyValues) { + TodayPresentationDependencyPreparation.prepare( + &dependencies, + fetchDisplayOptionsUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .fetchTodayDisplayOptionsUseCase, + fetchTodosUseCase: todoGraphSet.todoUseCaseGraph.fetchTodosUseCase, + updateDisplayOptionsUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .updateTodayDisplayOptionsUseCase + ) + } + + func prepareNotificationDependencies(_ dependencies: inout DependencyValues) { + NotificationDependencyPreparation.prepareQuery( + &dependencies, + fetchQueryUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .fetchPushNotificationQueryUseCase, + updateQueryUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .updatePushNotificationQueryUseCase + ) + NotificationDependencyPreparation.prepareList( + &dependencies, + fetchNotificationsUseCase: pushNotificationGraphSet + .pushNotificationUseCaseGraph + .fetchPushNotificationsUseCase, + deleteNotificationUseCase: pushNotificationGraphSet + .pushNotificationUseCaseGraph + .deletePushNotificationUseCase, + undoDeleteNotificationUseCase: pushNotificationGraphSet + .pushNotificationUseCaseGraph + .undoDeletePushNotificationUseCase + ) + NotificationDependencyPreparation.prepareReadState( + &dependencies, + toggleNotificationReadUseCase: pushNotificationGraphSet + .pushNotificationUseCaseGraph + .togglePushNotificationReadUseCase + ) + } + + func prepareProfileDependencies(_ dependencies: inout DependencyValues) { + ProfilePresentationDependencyPreparation.prepareUser( + &dependencies, + fetchUserDataUseCase: userProfileGraphSet.userDataUseCaseGraph.fetchUserDataUseCase, + fetchProfileImageDataUseCase: userProfileGraphSet + .profileImageDataUseCaseGraph + .fetchProfileImageDataUseCase, + upsertStatusMessageUseCase: userProfileGraphSet + .userDataUseCaseGraph + .upsertStatusMessageUseCase + ) + ProfilePresentationDependencyPreparation.prepareActivity( + &dependencies, + fetchTodosUseCase: todoGraphSet.todoUseCaseGraph.fetchTodosUseCase, + networkConnectivityUseCase: networkConnectivityGraphSet + .networkConnectivityUseCaseGraph + .observeNetworkConnectivityUseCase, + fetchHeatmapActivityTypesUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .fetchHeatmapActivityTypesUseCase, + updateHeatmapActivityTypesUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .updateHeatmapActivityTypesUseCase + ) + ProfilePresentationDependencyPreparation.prepareSettingsSession( + &dependencies, + deleteAuthUseCase: authenticationGraphSet.authenticationUseCaseGraph.deleteAuthUseCase, + signOutUseCase: authenticationGraphSet.authenticationUseCaseGraph.signOutUseCase, + networkConnectivityUseCase: networkConnectivityGraphSet + .networkConnectivityUseCaseGraph + .observeNetworkConnectivityUseCase + ) + ProfilePresentationDependencyPreparation.prepareSettingsAppearance( + &dependencies, + systemThemeUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .observeSystemThemeUseCase, + updateSystemThemeUseCase: userPreferencesGraphSet + .userPreferencesUseCaseGraph + .updateSystemThemeUseCase + ) + ProfilePresentationDependencyPreparation.prepareSettingsStorage( + &dependencies, + fetchWebPageImageDirSizeUseCase: webPageGraphSet + .webPageImageUseCaseGraph + .fetchWebPageImageDirSizeUseCase, + clearWebPageImageDirectoryUseCase: webPageGraphSet + .webPageImageUseCaseGraph + .clearWebPageImageDirectoryUseCase + ) + ProfilePresentationDependencyPreparation.prepareAccount( + &dependencies, + fetchAuthProvidersUseCase: authenticationGraphSet + .authProviderUseCaseGraph + .fetchAuthProvidersUseCase, + linkAuthProviderUseCase: authenticationGraphSet + .authProviderUseCaseGraph + .linkAuthProviderUseCase, + unlinkAuthProviderUseCase: authenticationGraphSet + .authProviderUseCaseGraph + .unlinkAuthProviderUseCase + ) + ProfilePresentationDependencyPreparation.preparePushSettings( + &dependencies, + fetchPushSettingsUseCase: pushNotificationGraphSet + .pushNotificationUseCaseGraph + .fetchPushSettingsUseCase, + updatePushSettingsUseCase: pushNotificationGraphSet + .pushNotificationUseCaseGraph + .updatePushSettingsUseCase + ) + } +} diff --git a/Application/App/Sources/App/DevLogApp.swift b/Application/App/Sources/App/DevLogApp.swift index bb7215c3..4cc23eae 100644 --- a/Application/App/Sources/App/DevLogApp.swift +++ b/Application/App/Sources/App/DevLogApp.swift @@ -6,32 +6,23 @@ // import SwiftUI -import Core -import Data -import Domain import Presentation import Widget @main struct DevLogApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate - @Environment(\.diContainer) var container: DIContainer @Environment(\.scenePhase) var scenePhase @State private var windowEvent = TodoEditorWindowEvent() @State private var syncDate = Date() init() { - AppAssembler().assemble(AppDIContainer.shared) + AppGraph.shared.preparePresentationDependencies() } var body: some Scene { WindowGroup { RootView( - sessionUseCase: container.resolve(ObserveAuthSessionUseCase.self), - networkConnectivityUseCase: container.resolve(ObserveNetworkConnectivityUseCase.self), - systemThemeUseCase: container.resolve(ObserveSystemThemeUseCase.self), - trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self), - checkAppUpdateUseCase: container.resolve(CheckAppUpdateUseCase.self), widgetURLTab: { MainTab(widgetURL: $0) }, windowEvent: windowEvent, pushNotificationTodoIdPublisher: PushNotificationRoute.shared.observe(), @@ -51,7 +42,11 @@ struct DevLogApp: App { guard !Calendar.current.isDate(syncDate, inSameDayAs: now) else { return } syncDate = now - container.resolve(WidgetSyncEventBus.self).publish(.syncRequested) + AppGraph.shared + .widgetGraphSet + .widgetSyncEventBusGraph + .widgetSyncEventBus + .publish(.syncRequested) } } WindowGroup(id: TodoEditorWindowValue.sceneId, for: TodoEditorWindowValue.self) { value in diff --git a/Application/Presentation/Entry/Sources/Login/LoginView.swift b/Application/Presentation/Entry/Sources/Login/LoginView.swift index 58ce4316..49a0e46a 100644 --- a/Application/Presentation/Entry/Sources/Login/LoginView.swift +++ b/Application/Presentation/Entry/Sources/Login/LoginView.swift @@ -15,13 +15,11 @@ struct LoginView: View { @Environment(\.sceneWidth) var sceneWidth @State private var store: StoreOf - init(signInUseCase: SignInUseCase) { + init() { self._store = State(initialValue: Store( initialState: LoginFeature.State() ) { LoginFeature() - } withDependencies: { - $0.signInUseCase = signInUseCase }) } diff --git a/Application/Presentation/Entry/Sources/Main/MainView.swift b/Application/Presentation/Entry/Sources/Main/MainView.swift index 9be0b5a3..1e3dc84c 100644 --- a/Application/Presentation/Entry/Sources/Main/MainView.swift +++ b/Application/Presentation/Entry/Sources/Main/MainView.swift @@ -6,8 +6,6 @@ // import SwiftUI -import Core -import Domain import HomeTab import NotificationTab import ProfileTab @@ -26,23 +24,19 @@ struct MainView: View { private let windowEvent: TodoEditorWindowEvent init( - container: DIContainer, windowEvent: TodoEditorWindowEvent, selectedTab: Binding ) { self._store = State(initialValue: Store(initialState: MainFeature.State()) { MainFeature() - } withDependencies: { - $0.observeUnreadPushCountUseCase = container.resolve(ObserveUnreadPushCountUseCase.self) - $0.trackAnalyticsEventUseCase = container.resolve(TrackAnalyticsEventUseCase.self) }) - self._todoWindowCoordinator = State(initialValue: TodoWindowCoordinator(container: container)) - self._homeViewCoordinator = State(initialValue: HomeViewCoordinator(container: container)) - self._todayViewCoordinator = State(initialValue: TodayViewCoordinator(container: container)) + self._todoWindowCoordinator = State(initialValue: TodoWindowCoordinator()) + self._homeViewCoordinator = State(initialValue: HomeViewCoordinator()) + self._todayViewCoordinator = State(initialValue: TodayViewCoordinator()) self._pushNotificationListViewCoordinator = State( - initialValue: PushNotificationListViewCoordinator(container: container) + initialValue: PushNotificationListViewCoordinator() ) - self._profileViewCoordinator = State(initialValue: ProfileViewCoordinator(container: container)) + self._profileViewCoordinator = State(initialValue: ProfileViewCoordinator()) self._selectedTab = selectedTab self.windowEvent = windowEvent diff --git a/Application/Presentation/Entry/Sources/Root/RootView.swift b/Application/Presentation/Entry/Sources/Root/RootView.swift index 6a24a21f..b162c51f 100644 --- a/Application/Presentation/Entry/Sources/Root/RootView.swift +++ b/Application/Presentation/Entry/Sources/Root/RootView.swift @@ -7,12 +7,9 @@ import SwiftUI import Combine -import Core -import Domain import PresentationShared public struct RootView: View { - @Environment(\.diContainer) var container: DIContainer @State private var store: StoreOf private let widgetURLTab: (URL) -> MainTab? private let windowEvent: TodoEditorWindowEvent @@ -20,11 +17,6 @@ public struct RootView: View { private let clearPushNotificationRoute: () -> Void public init( - sessionUseCase: ObserveAuthSessionUseCase, - networkConnectivityUseCase: ObserveNetworkConnectivityUseCase, - systemThemeUseCase: ObserveSystemThemeUseCase, - trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase, - checkAppUpdateUseCase: CheckAppUpdateUseCase, widgetURLTab: @escaping (URL) -> MainTab?, windowEvent: TodoEditorWindowEvent, pushNotificationTodoIdPublisher: AnyPublisher, @@ -32,12 +24,6 @@ public struct RootView: View { ) { self._store = State(initialValue: Store(initialState: RootFeature.State()) { RootFeature() - } withDependencies: { - $0.observeAuthSessionUseCase = sessionUseCase - $0.rootNetworkConnectivityUseCase = networkConnectivityUseCase - $0.rootSystemThemeUseCase = systemThemeUseCase - $0.trackAnalyticsEventUseCase = trackAnalyticsEventUseCase - $0.checkAppUpdateUseCase = checkAppUpdateUseCase }) self.widgetURLTab = widgetURLTab self.windowEvent = windowEvent @@ -51,12 +37,11 @@ public struct RootView: View { if let signIn = store.signIn { if signIn { MainView( - container: container, windowEvent: windowEvent, selectedTab: $store.selectedMainTab ) } else { - LoginView(signInUseCase: container.resolve(SignInUseCase.self)) + LoginView() } } } @@ -87,9 +72,6 @@ public struct RootView: View { initialState: TodoDetailFeature.State(todoId: todoId, showEditButton: false) ) { TodoDetailFeature() - } withDependencies: { - $0.fetchTodoByIdUseCase = container.resolve(FetchTodoByIdUseCase.self) - $0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self) }) .toolbar { ToolbarLeadingButton { diff --git a/Application/Presentation/Entry/Sources/WindowGroup/TodoEditorWindowView.swift b/Application/Presentation/Entry/Sources/WindowGroup/TodoEditorWindowView.swift index 75e1ffb6..c304cd17 100644 --- a/Application/Presentation/Entry/Sources/WindowGroup/TodoEditorWindowView.swift +++ b/Application/Presentation/Entry/Sources/WindowGroup/TodoEditorWindowView.swift @@ -6,12 +6,10 @@ // import SwiftUI -import Core import Domain import PresentationShared public struct TodoEditorWindowView: View { - @Environment(\.diContainer) private var container: DIContainer @State private var windowScene: UIWindowScene? private let value: TodoEditorWindowValue private let windowEvent: TodoEditorWindowEvent @@ -31,12 +29,6 @@ public struct TodoEditorWindowView: View { TodoEditorView( store: Store(initialState: TodoEditorFeature.State(category: windowCategory.todoCategory)) { TodoEditorFeature() - } withDependencies: { - $0.fetchTodoCategoryPreferencesUseCase = container.resolve( - FetchTodoCategoryPreferencesUseCase.self - ) - $0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self) - $0.upsertTodoUseCase = container.resolve(UpsertTodoUseCase.self) }, onCreateSuccess: create, onClose: closeWindow @@ -45,12 +37,6 @@ public struct TodoEditorWindowView: View { TodoEditorView( store: Store(initialState: TodoEditorFeature.State(todo: windowTodo.todo)) { TodoEditorFeature() - } withDependencies: { - $0.fetchTodoCategoryPreferencesUseCase = container.resolve( - FetchTodoCategoryPreferencesUseCase.self - ) - $0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self) - $0.upsertTodoUseCase = container.resolve(UpsertTodoUseCase.self) }, onUpdateSuccess: update, onClose: closeWindow diff --git a/Application/Presentation/Entry/Sources/WindowGroup/TodoWindowCoordinator.swift b/Application/Presentation/Entry/Sources/WindowGroup/TodoWindowCoordinator.swift index ac8c4a0a..1f9c6fba 100644 --- a/Application/Presentation/Entry/Sources/WindowGroup/TodoWindowCoordinator.swift +++ b/Application/Presentation/Entry/Sources/WindowGroup/TodoWindowCoordinator.swift @@ -7,14 +7,14 @@ import Combine import Foundation -import Core import Domain import PresentationShared @MainActor @Observable final class TodoWindowCoordinator { - private let container: DIContainer + @ObservationIgnored + @Dependency(\.trackAnalyticsEventUseCase) private var trackAnalyticsEventUseCase @ObservationIgnored private var listStore: StoreOf? @ObservationIgnored @@ -22,10 +22,6 @@ final class TodoWindowCoordinator { @ObservationIgnored private var cancellable: AnyCancellable? - init(container: DIContainer) { - self.container = container - } - func bindWindowEvent(_ windowEvent: TodoEditorWindowEvent) { guard cancellable == nil else { return } @@ -43,15 +39,6 @@ final class TodoWindowCoordinator { let listStore = Store(initialState: TodoListFeature.State(category: category)) { TodoListFeature() - } withDependencies: { - $0.fetchTodoCategoryPreferencesUseCase = self.container.resolve(FetchTodoCategoryPreferencesUseCase.self) - $0.fetchReferenceItemsUseCase = self.container.resolve(FetchReferenceItemsUseCase.self) - $0.todoListFetchTodosUseCase = self.container.resolve(FetchTodosUseCase.self) - $0.fetchTodoByIdUseCase = self.container.resolve(FetchTodoByIdUseCase.self) - $0.upsertTodoUseCase = self.container.resolve(UpsertTodoUseCase.self) - $0.todoListDeleteTodoUseCase = self.container.resolve(DeleteTodoUseCase.self) - $0.todoListUndoDeleteTodoUseCase = self.container.resolve(UndoDeleteTodoUseCase.self) - $0.trackAnalyticsEventUseCase = self.container.resolve(TrackAnalyticsEventUseCase.self) } self.listStore = listStore return listStore @@ -73,11 +60,6 @@ final class TodoWindowCoordinator { ) ) { TodoDetailFeature() - } withDependencies: { - $0.fetchTodoCategoryPreferencesUseCase = self.container.resolve(FetchTodoCategoryPreferencesUseCase.self) - $0.fetchTodoByIdUseCase = self.container.resolve(FetchTodoByIdUseCase.self) - $0.fetchReferenceItemsUseCase = self.container.resolve(FetchReferenceItemsUseCase.self) - $0.upsertTodoUseCase = self.container.resolve(UpsertTodoUseCase.self) } self.detailStore = detailStore return detailStore @@ -86,7 +68,7 @@ final class TodoWindowCoordinator { private func handleTodoEditorSubmit(_ submit: TodoEditorWindowSubmit) { switch submit { case .create(let value): - container.resolve(TrackAnalyticsEventUseCase.self).execute(.todoCreate) + trackAnalyticsEventUseCase.execute(.todoCreate) if let listStore, value.matchesCreate(category: listStore.category, source: .list) { listStore.send(.view(.refresh)) diff --git a/Application/Presentation/HomeTab/Sources/Home/Home/HomeViewCoordinator.swift b/Application/Presentation/HomeTab/Sources/Home/Home/HomeViewCoordinator.swift index 2003fdf6..e2b585b2 100644 --- a/Application/Presentation/HomeTab/Sources/Home/Home/HomeViewCoordinator.swift +++ b/Application/Presentation/HomeTab/Sources/Home/Home/HomeViewCoordinator.swift @@ -7,7 +7,6 @@ import Combine import Foundation -import Core import Domain import PresentationShared @@ -16,7 +15,10 @@ import PresentationShared public final class HomeViewCoordinator { let store: StoreOf public let router = NavigationRouter() - private let container: DIContainer + @ObservationIgnored + @Dependency(\.homeTodoMutationEventBus) private var todoMutationEventBus + @ObservationIgnored + @Dependency(\.homeFetchRecentSearchQueriesUseCase) private var fetchRecentSearchQueriesUseCase @ObservationIgnored private var cancellables = Set() @ObservationIgnored @@ -24,24 +26,9 @@ public final class HomeViewCoordinator { @ObservationIgnored private var isWindowEventBound = false - public init(container: DIContainer) { - self.container = container + public init() { self.store = Store(initialState: HomeFeature.State()) { HomeFeature() - } withDependencies: { - $0.fetchTodoCategoryPreferencesUseCase = container.resolve(FetchTodoCategoryPreferencesUseCase.self) - $0.homeUpdateTodoCategoryPreferencesUseCase = container.resolve( - UpdateTodoCategoryPreferencesUseCase.self - ) - $0.homeAddWebPageUseCase = container.resolve(AddWebPageUseCase.self) - $0.homeDeleteWebPageUseCase = container.resolve(DeleteWebPageUseCase.self) - $0.homeUndoDeleteWebPageUseCase = container.resolve(UndoDeleteWebPageUseCase.self) - $0.homeFetchTodosUseCase = container.resolve(FetchTodosUseCase.self) - $0.homeFetchWebPagesUseCase = container.resolve(FetchWebPagesUseCase.self) - $0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self) - $0.upsertTodoUseCase = container.resolve(UpsertTodoUseCase.self) - $0.homeNetworkConnectivityUseCase = container.resolve(ObserveNetworkConnectivityUseCase.self) - $0.trackAnalyticsEventUseCase = container.resolve(TrackAnalyticsEventUseCase.self) } self.store.send(.view(.startObserving)) } @@ -58,8 +45,7 @@ public final class HomeViewCoordinator { guard isTodoMutationEventBound == false else { return } isTodoMutationEventBound = true - let bus = container.resolve(TodoMutationEventBus.self) - bus.observe() + todoMutationEventBus.observe() .receive(on: DispatchQueue.main) .sink { [weak self] event in guard let self else { return } @@ -88,14 +74,10 @@ public final class HomeViewCoordinator { func makeSearchStore() -> StoreOf { Store( initialState: SearchFeature.State( - recentQueries: container.resolve(FetchRecentSearchQueriesUseCase.self).execute() + recentQueries: fetchRecentSearchQueriesUseCase.execute() ) ) { SearchFeature() - } withDependencies: { - $0.searchFetchWebPagesUseCase = self.container.resolve(FetchWebPagesUseCase.self) - $0.searchFetchTodosUseCase = self.container.resolve(FetchTodosUseCase.self) - $0.searchUpdateRecentQueriesUseCase = self.container.resolve(UpdateRecentSearchQueriesUseCase.self) } } } diff --git a/Application/Presentation/HomeTab/Sources/Home/Search/SearchView.swift b/Application/Presentation/HomeTab/Sources/Home/Search/SearchView.swift index f51c790c..a78d3b35 100644 --- a/Application/Presentation/HomeTab/Sources/Home/Search/SearchView.swift +++ b/Application/Presentation/HomeTab/Sources/Home/Search/SearchView.swift @@ -6,13 +6,11 @@ // import SwiftUI -import Core import Domain import PresentationShared struct SearchView: View { @Environment(\.dismiss) private var dismiss - @Environment(\.diContainer) private var container: DIContainer @State private var router = NavigationRouter() @State var store: StoreOf @@ -30,13 +28,6 @@ struct SearchView: View { initialState: TodoDetailFeature.State(todoId: todoId, showEditButton: true) ) { TodoDetailFeature() - } withDependencies: { - $0.fetchTodoCategoryPreferencesUseCase = container.resolve( - FetchTodoCategoryPreferencesUseCase.self - ) - $0.fetchTodoByIdUseCase = container.resolve(FetchTodoByIdUseCase.self) - $0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self) - $0.upsertTodoUseCase = container.resolve(UpsertTodoUseCase.self) }) case .web(let page): WebView(url: page.url) diff --git a/Application/Presentation/NotificationTab/Sources/PushNotificationListViewCoordinator.swift b/Application/Presentation/NotificationTab/Sources/PushNotificationListViewCoordinator.swift index 7fe59e27..88d3ca0d 100644 --- a/Application/Presentation/NotificationTab/Sources/PushNotificationListViewCoordinator.swift +++ b/Application/Presentation/NotificationTab/Sources/PushNotificationListViewCoordinator.swift @@ -6,7 +6,6 @@ // import Foundation -import Core import Domain import PresentationShared @@ -14,15 +13,13 @@ import PresentationShared @Observable public final class PushNotificationListViewCoordinator { let store: StoreOf - private let container: DIContainer @ObservationIgnored private var todoDetailStore: StoreOf? @ObservationIgnored private var fetchNotificationsTask: Task? - public init(container: DIContainer) { - self.container = container - let fetchQueryUseCase = container.resolve(FetchPushNotificationQueryUseCase.self) + public init() { + @Dependency(\.fetchPushNotificationQueryUseCase) var fetchQueryUseCase self.store = Store( initialState: PushNotificationListFeature.State( @@ -30,12 +27,6 @@ public final class PushNotificationListViewCoordinator { ) ) { PushNotificationListFeature() - } withDependencies: { - $0.fetchPushNotificationsUseCase = container.resolve(FetchPushNotificationsUseCase.self) - $0.deletePushNotificationUseCase = container.resolve(DeletePushNotificationUseCase.self) - $0.undoDeletePushNotificationUseCase = container.resolve(UndoDeletePushNotificationUseCase.self) - $0.togglePushNotificationReadUseCase = container.resolve(TogglePushNotificationReadUseCase.self) - $0.updatePushNotificationQueryUseCase = container.resolve(UpdatePushNotificationQueryUseCase.self) } } @@ -62,8 +53,6 @@ public final class PushNotificationListViewCoordinator { return todoDetailStore } - let fetchTodoUseCase = container.resolve(FetchTodoByIdUseCase.self) - let fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self) let todoDetailStore = Store( initialState: TodoDetailFeature.State( todoId: todoId, @@ -71,9 +60,6 @@ public final class PushNotificationListViewCoordinator { ) ) { TodoDetailFeature() - } withDependencies: { - $0.fetchTodoByIdUseCase = fetchTodoUseCase - $0.fetchReferenceItemsUseCase = fetchReferenceItemsUseCase } self.todoDetailStore = todoDetailStore return todoDetailStore diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailPreviewModifier.swift b/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailPreviewModifier.swift index ce193ec1..150185df 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailPreviewModifier.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailPreviewModifier.swift @@ -7,7 +7,6 @@ import SwiftUI import ComposableArchitecture -import Core import Domain public extension View { @@ -17,7 +16,6 @@ public extension View { } private struct TodoDetailPreviewModifier: ViewModifier { - @Environment(\.diContainer) private var container let todoId: String func body(content: Content) -> some View { @@ -37,9 +35,6 @@ private struct TodoDetailPreviewModifier: ViewModifier { ) ) { TodoDetailFeature() - } withDependencies: { - $0.fetchTodoByIdUseCase = container.resolve(FetchTodoByIdUseCase.self) - $0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self) } return UIHostingController(rootView: TodoDetailPreviewView(store: store)) } diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift index 0b9832de..9cb1e449 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Detail/TodoDetailView.swift @@ -11,7 +11,6 @@ import Core import Domain public struct TodoDetailView: View { - @Environment(\.diContainer) private var container: DIContainer @Environment(\.openWindow) private var openWindow @Environment(\.isiOSAppOnMac) private var isiOSAppOnMac @State var store: StoreOf diff --git a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift index 70549c04..5bbbf173 100644 --- a/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift +++ b/Application/Presentation/PresentationShared/Sources/Todo/Editor/TodoEditorView.swift @@ -11,7 +11,6 @@ import Core import Domain public struct TodoEditorView: View { - @Environment(\.diContainer) private var container: DIContainer @Environment(\.dismiss) private var dismiss @Environment(\.isiOSAppOnMac) private var isiOSAppOnMac @State var store: StoreOf @@ -259,9 +258,6 @@ public struct TodoEditorView: View { initialState: TodoDetailFeature.State(todoId: item.id, showEditButton: false) ) { TodoDetailFeature() - } withDependencies: { - $0.fetchTodoByIdUseCase = container.resolve(FetchTodoByIdUseCase.self) - $0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self) }) .toolbar { ToolbarLeadingButton { diff --git a/Application/Presentation/ProfileTab/Sources/Profile/ProfileViewCoordinator.swift b/Application/Presentation/ProfileTab/Sources/Profile/ProfileViewCoordinator.swift index 3a7648f1..99741a82 100644 --- a/Application/Presentation/ProfileTab/Sources/Profile/ProfileViewCoordinator.swift +++ b/Application/Presentation/ProfileTab/Sources/Profile/ProfileViewCoordinator.swift @@ -6,7 +6,6 @@ // import Foundation -import Core import Domain import PresentationShared @@ -16,31 +15,13 @@ public final class ProfileViewCoordinator { let store: StoreOf let settingsStore: StoreOf var router = NavigationRouter() - private let container: DIContainer - public init(container: DIContainer) { - self.container = container + public init() { self.store = Store(initialState: ProfileFeature.State()) { ProfileFeature() - } withDependencies: { - $0.profileFetchUserDataUseCase = container.resolve(FetchUserDataUseCase.self) - $0.profileFetchImageDataUseCase = container.resolve(FetchProfileImageDataUseCase.self) - $0.profileFetchTodosUseCase = container.resolve(FetchTodosUseCase.self) - $0.profileUpsertStatusMessageUseCase = container.resolve(UpsertStatusMessageUseCase.self) - $0.profileNetworkConnectivityUseCase = container.resolve(ObserveNetworkConnectivityUseCase.self) - $0.profileFetchHeatmapActivityTypesUseCase = container.resolve(FetchHeatmapActivityTypesUseCase.self) - $0.profileUpdateHeatmapActivityTypesUseCase = container.resolve(UpdateHeatmapActivityTypesUseCase.self) } self.settingsStore = Store(initialState: SettingsFeature.State()) { SettingsFeature() - } withDependencies: { - $0.deleteAuthUseCase = container.resolve(DeleteAuthUseCase.self) - $0.signOutUseCase = container.resolve(SignOutUseCase.self) - $0.profileNetworkConnectivityUseCase = container.resolve(ObserveNetworkConnectivityUseCase.self) - $0.profileSystemThemeUseCase = container.resolve(ObserveSystemThemeUseCase.self) - $0.updateSystemThemeUseCase = container.resolve(UpdateSystemThemeUseCase.self) - $0.fetchWebPageImageDirSizeUseCase = container.resolve(FetchWebPageImageDirSizeUseCase.self) - $0.clearWebPageImageDirectoryUseCase = container.resolve(ClearWebPageImageDirectoryUseCase.self) } self.store.send(.startObserving) self.settingsStore.send(.startObserving) @@ -53,19 +34,12 @@ public final class ProfileViewCoordinator { func makeAccountStore() -> StoreOf { Store(initialState: AccountFeature.State()) { AccountFeature() - } withDependencies: { - $0.fetchAuthProvidersUseCase = self.container.resolve(FetchAuthProvidersUseCase.self) - $0.linkAuthProviderUseCase = self.container.resolve(LinkAuthProviderUseCase.self) - $0.unlinkAuthProviderUseCase = self.container.resolve(UnlinkAuthProviderUseCase.self) } } func makePushNotificationSettingsStore() -> StoreOf { Store(initialState: PushNotificationSettingsFeature.State()) { PushNotificationSettingsFeature() - } withDependencies: { - $0.fetchPushSettingsUseCase = self.container.resolve(FetchPushSettingsUseCase.self) - $0.updatePushSettingsUseCase = self.container.resolve(UpdatePushSettingsUseCase.self) } } @@ -77,9 +51,6 @@ public final class ProfileViewCoordinator { ) ) { TodoDetailFeature() - } withDependencies: { - $0.fetchTodoByIdUseCase = self.container.resolve(FetchTodoByIdUseCase.self) - $0.fetchReferenceItemsUseCase = self.container.resolve(FetchReferenceItemsUseCase.self) } } } diff --git a/Application/Presentation/TodayTab/Sources/Today/TodayViewCoordinator.swift b/Application/Presentation/TodayTab/Sources/Today/TodayViewCoordinator.swift index c63fc1e2..3f40c2cb 100644 --- a/Application/Presentation/TodayTab/Sources/Today/TodayViewCoordinator.swift +++ b/Application/Presentation/TodayTab/Sources/Today/TodayViewCoordinator.swift @@ -6,7 +6,6 @@ // import Foundation -import Core import Domain import PresentationShared @@ -16,20 +15,14 @@ public final class TodayViewCoordinator { let store: StoreOf public let router = NavigationRouter() - public init(container: DIContainer) { - let fetchDisplayOptionsUseCase = container.resolve(FetchTodayDisplayOptionsUseCase.self) + public init() { + @Dependency(\.todayFetchDisplayOptionsUseCase) var fetchDisplayOptionsUseCase self.store = Store( initialState: TodayFeature.State( displayOptions: fetchDisplayOptionsUseCase.execute() ) ) { TodayFeature() - } withDependencies: { - $0.todayFetchTodosUseCase = container.resolve(FetchTodosUseCase.self) - $0.fetchTodoByIdUseCase = container.resolve(FetchTodoByIdUseCase.self) - $0.upsertTodoUseCase = container.resolve(UpsertTodoUseCase.self) - $0.updateTodayDisplayOptionsUseCase = container.resolve(UpdateTodayDisplayOptionsUseCase.self) - $0.trackAnalyticsEventUseCase = container.resolve(TrackAnalyticsEventUseCase.self) } } From 6aa32426dc5d06b823fddc09b3ffa463a53f4e79 Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 18:07:08 +0900 Subject: [PATCH 18/19] =?UTF-8?q?refactor:=20=EA=B8=B0=EC=A1=B4=20DIContai?= =?UTF-8?q?ner=EC=99=80=20Assembler=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/rules/architecture.md | 14 +- .agents/rules/project-workflows.md | 4 +- .../Sources/App/Assembler/AppAssembler.swift | 28 -- .../App/Assembler/AppLayerAssembler.swift | 32 -- Application/Core/Sources/Assembler.swift | 10 - Application/Core/Sources/DIContainer.swift | 105 ------ Application/Core/Sources/DIContainerKey.swift | 19 -- Application/Data/Sources/DataAssembler.swift | 161 ---------- .../Domain/Sources/DomainAssembler.swift | 301 ------------------ .../Infra/Sources/InfraAssembler.swift | 102 ------ .../Sources/PersistenceAssembler.swift | 31 -- .../Sources/Widget/WidgetAssembler.swift | 54 ---- README.md | 4 +- 13 files changed, 11 insertions(+), 854 deletions(-) delete mode 100644 Application/App/Sources/App/Assembler/AppAssembler.swift delete mode 100644 Application/App/Sources/App/Assembler/AppLayerAssembler.swift delete mode 100644 Application/Core/Sources/Assembler.swift delete mode 100644 Application/Core/Sources/DIContainer.swift delete mode 100644 Application/Core/Sources/DIContainerKey.swift delete mode 100644 Application/Data/Sources/DataAssembler.swift delete mode 100644 Application/Domain/Sources/DomainAssembler.swift delete mode 100644 Application/Infra/Sources/InfraAssembler.swift delete mode 100644 Application/Persistence/Sources/PersistenceAssembler.swift delete mode 100644 Application/Widget/Sources/Widget/WidgetAssembler.swift diff --git a/.agents/rules/architecture.md b/.agents/rules/architecture.md index 661fa0ac..455d3179 100644 --- a/.agents/rules/architecture.md +++ b/.agents/rules/architecture.md @@ -18,7 +18,7 @@ Read this file before work that changes any of these areas: - Module boundaries or file ownership across `Application/*`, `Libraries/*`, and `Widget/*` targets. - Swift imports or Tuist target dependencies. -- DI assembler wiring or same-layer dependency injection. +- DI graph wiring or same-layer dependency injection. - Repository, service, store, or use case contracts. - Firebase, social login, network, link metadata, notification, or WidgetKit dependency placement. - Widget snapshot, App Group, or widget deep-link data flow. @@ -110,7 +110,7 @@ flowchart TD ```mermaid flowchart TD - App["App\nComposition root\nApp lifecycle\nAssembler wiring"] + App["App\nComposition root\nApp lifecycle\nCradle graph wiring"] Presentation["Presentation\nSwiftUI views\nViewModels\nCoordinators\nUI state"] Domain["Domain\nEntities\nRepository protocols\nUse cases"] Data["Data\nRepository implementations\nDTOs\nMappers\nService/store protocols"] @@ -160,15 +160,15 @@ flowchart TD | Layer | Owns | Allowed direction | Ask before | | --- | --- | --- | --- | | `ThirdParty` | external package declarations, product linkage, marker sources | No DevLog target dependency; may be depended on by any target | Adding DevLog feature, service, adapter, or layer dependency; changing package versions or products outside the requested scope | -| `Core` | DI primitives, logger, shared value/query types, display options, activity kinds, lightweight widget bridge values | No DevLog layer dependency; `ThirdParty` when needed | Moving domain entities into Core | +| `Core` | logger, shared value/query types, display options, activity kinds, lightweight widget bridge values | No DevLog layer dependency; `ThirdParty` when needed | Moving domain entities into Core | | `Domain` | entities, repository protocols, use cases | Core, `ThirdParty` when needed | Adding Data, Infra, Persistence, Presentation, App, or Widget UI dependency | | `Data` | repository implementations, DTOs, mappers, data protocols, widget repository/updater/sync contracts | Domain, Core, `ThirdParty` when needed | Adding WidgetKit, storage, WidgetCore snapshot model/factory usage, or platform implementation details; moving concrete widget handlers into Data | | `Infra` | application infrastructure service implementations for social login, network, metadata, and messaging | Data, Core, `ThirdParty` when needed | Adding any Domain dependency or SDK service contract coupling | | `Persistence` | local stores, image cache, non-widget app persistence | Data, Core, `ThirdParty` when needed | Adding WidgetCore, WidgetKit reload, Widget, widget snapshot generation, or widget bridge ownership | | `Presentation` | UI, view models, coordinators, presentation state, narrow presentation-scoped platform side effects | Domain, Core, `ThirdParty` when needed | Adding Data, Infra, Persistence, or App dependency; expanding platform service ownership beyond UI-side effects | | `MarkdownRenderer` | public SwiftUI renderer and reference value, internal WebKit bridge, renderer resources, TypeScript Tooling, renderer tests | system frameworks, `ThirdParty` when needed | Adding a DevLog application layer dependency, exposing WebKit bridge types, adding another Presentation importer, or re-exporting the module | -| `Widget` | app-side widget bridge, sync bus implementation, sync/session handlers, snapshot generation/persistence orchestration, WidgetKit reload bridge, widget assembler | Data, Core, WidgetCore, `ThirdParty` when needed | Adding Domain, Infra, Persistence, Presentation, or App dependency | -| `App` | composition root, lifecycle, assembler wiring, app target ownership for widget extension embedding | Concrete app layers, `ThirdParty` for framework linking | Moving feature logic into App | +| `Widget` | app-side widget bridge, sync bus implementation, sync/session handlers, snapshot generation/persistence orchestration, WidgetKit reload bridge, provider graph | Data, Core, WidgetCore, `ThirdParty` when needed | Adding Domain, Infra, Persistence, Presentation, or App dependency | +| `App` | composition root, lifecycle, Cradle graph wiring, app target ownership for widget extension embedding | Concrete app layers, `ThirdParty` for framework linking | Moving feature logic into App | | `WidgetCore` | widget snapshot models, factories, app-group keys/defaults store, deep links, pure snapshot logic | Core, `ThirdParty` when needed | Adding Domain, Data, Infra, Persistence, Presentation, App, or Widget dependency | | `WidgetExtension` | WidgetKit rendering and timeline plumbing | WidgetCore, `ThirdParty` when needed | Calling app/domain services directly | @@ -179,7 +179,7 @@ flowchart TD - `EntryTests` validates `Entry` through `Application/Presentation/Entry/Tests/**/*.swift`. - `HomeTab`, `TodayTab`, `NotificationTab`, and `ProfileTab` remain tab-specific feature targets and each target owns the `Domain` references it needs. - `PresentationShared` owns shared Todo, Search, Loading UI, and presentation contracts. -- `App` owns composition root, lifecycle, and assembler wiring. It must not take ownership of presentation feature or root flows. +- `App` owns composition root, lifecycle, and Cradle graph wiring. It must not take ownership of presentation feature or root flows. ## MarkdownRenderer module boundary @@ -194,7 +194,7 @@ flowchart TD Do not inject dependencies between types that belong to the same layer. -This rule covers initializer injection, stored-property injection, environment injection, and resolving same-layer types through `DIContainer`. +This rule covers initializer injection, stored-property injection, environment injection, and resolving same-layer types through a runtime resolver. The only allowed exception is a SwiftUI `View` file in `Application/Presentation` receiving same-layer presentation objects such as a ViewModel, Coordinator, or Store for UI composition. diff --git a/.agents/rules/project-workflows.md b/.agents/rules/project-workflows.md index e43718f0..1772d6f9 100644 --- a/.agents/rules/project-workflows.md +++ b/.agents/rules/project-workflows.md @@ -72,7 +72,7 @@ This reference holds DevLog-specific working rules that should live with the pro ## Layer-internal dependency injection - Do not inject dependencies between types that belong to the same layer. -- This includes initializer injection, stored-property injection, environment injection, and resolving same-layer types through `DIContainer`. +- This includes initializer injection, stored-property injection, environment injection, and resolving same-layer types through a runtime resolver. - The only allowed exception is a SwiftUI `View` file in `Application/Presentation` receiving same-layer presentation objects such as a ViewModel, Coordinator, or Store for UI composition. - The exception does not apply to non-View files in Presentation, and does not apply to Core, Domain, Data, Infra, Persistence, Widget, App, WidgetCore, or WidgetExtension. @@ -100,7 +100,7 @@ This reference holds DevLog-specific working rules that should live with the pro - Widget UI should consume snapshot data, not app/domain services. - `WidgetCore` should stay free of Domain, Data, Infra, Persistence, Presentation, and App dependencies unless the user explicitly approves a boundary change. -- `Widget` owns the app-side widget bridge: sync event bus implementation, sync event handlers, session sync handler, auth-session sync provider, snapshot generation/persistence orchestration, WidgetKit reload bridge, and `WidgetAssembler`. +- `Widget` owns the app-side widget bridge: sync event bus implementation, sync event handlers, session sync handler, auth-session sync provider, snapshot generation/persistence orchestration, WidgetKit reload bridge, and provider graph. - `Data` owns widget-related contracts and repository implementations, including `WidgetSyncEventBus`, `WidgetSnapshotUpdater`, and `WidgetTodoSnapshotRepository`. Data should not own concrete widget handlers, WidgetCore snapshot model/factory usage, or WidgetKit reload behavior. - `Persistence` owns local persistence, user defaults, image store, and non-widget app persistence. - Prefer an app-driven snapshot flow: app/runtime event, Widget sync handler, Data snapshot input fetch, Widget snapshot update, App Group storage through WidgetCore contracts, WidgetExtension rendering. diff --git a/Application/App/Sources/App/Assembler/AppAssembler.swift b/Application/App/Sources/App/Assembler/AppAssembler.swift deleted file mode 100644 index 2a49d84a..00000000 --- a/Application/App/Sources/App/Assembler/AppAssembler.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// AppAssembler.swift -// DevLog -// -// Created by 최윤진 on 12/7/25. -// - -import Core -import Data -import Domain -import Infra -import Persistence -import Widget - -final class AppAssembler: Assembler { - private let assemblers: [Assembler] = [ - PersistenceAssembler(), - InfraAssembler(), - WidgetAssembler(), - DataAssembler(), - DomainAssembler(), - AppLayerAssembler() - ] - - func assemble(_ container: any DIContainer) { - assemblers.forEach { $0.assemble(container) } - } -} diff --git a/Application/App/Sources/App/Assembler/AppLayerAssembler.swift b/Application/App/Sources/App/Assembler/AppLayerAssembler.swift deleted file mode 100644 index 96d235d0..00000000 --- a/Application/App/Sources/App/Assembler/AppLayerAssembler.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// AppLayerAssembler.swift -// DevLog -// -// Created by opfic on 3/19/26. -// - -import Core -import Data - -final class AppLayerAssembler: Assembler { - func assemble(_ container: any DIContainer) { - container.register(FCMTokenSyncHandler.self) { - FCMTokenSyncHandler( - authService: container.resolve(AuthService.self), - messagingService: container.resolve(PushMessagingService.self), - userService: container.resolve(UserService.self) - ) - } - container.register(UserTimeZoneSyncHandler.self) { - UserTimeZoneSyncHandler( - authService: container.resolve(AuthService.self), - userService: container.resolve(UserService.self) - ) - } - container.register(PushNotificationOpenHandler.self) { - PushNotificationOpenHandler( - analyticsService: container.resolve(AnalyticsService.self) - ) - } - } -} diff --git a/Application/Core/Sources/Assembler.swift b/Application/Core/Sources/Assembler.swift deleted file mode 100644 index 44417fa1..00000000 --- a/Application/Core/Sources/Assembler.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// Assembler.swift -// Core -// -// Created by opfic on 5/15/26. -// - -public protocol Assembler { - func assemble(_ container: any DIContainer) -} diff --git a/Application/Core/Sources/DIContainer.swift b/Application/Core/Sources/DIContainer.swift deleted file mode 100644 index e12bc33e..00000000 --- a/Application/Core/Sources/DIContainer.swift +++ /dev/null @@ -1,105 +0,0 @@ -// -// DIContainer.swift -// Core -// -// Created by opfic on 5/15/26. -// - -import Foundation - -public struct DependencyName: Hashable, ExpressibleByStringLiteral { - public let rawValue: String - - public init(rawValue: String) { - self.rawValue = rawValue - } - - public init(stringLiteral value: String) { - self.rawValue = value - } -} - -public enum DependencyScope { - case singleton - case transient -} - -public protocol DIContainer { - func register( - _ type: T.Type, - name: DependencyName?, - scope: DependencyScope, - _ factory: @escaping () -> T - ) - - func resolve(_ type: T.Type, name: DependencyName?) -> T -} - -public extension DIContainer { - func register( - _ type: T.Type, - name: DependencyName? = nil, - scope: DependencyScope = .singleton, - _ factory: @escaping () -> T - ) { - register(type, name: name, scope: scope, factory) - } - - func resolve(_ type: T.Type, name: DependencyName? = nil) -> T { - resolve(type, name: name) - } -} - -public final class AppDIContainer: DIContainer { - public static let shared = AppDIContainer() - - private let lock = NSRecursiveLock() - - private init() { } - - private struct Key: Hashable { - let type: ObjectIdentifier - let name: DependencyName? - } - - private struct Registration { - let scope: DependencyScope - let factory: () -> Any - } - - private var registrations = [Key: Registration]() - private var singletons = [Key: Any]() - - public func register( - _ type: T.Type, - name: DependencyName? = nil, - scope: DependencyScope = .singleton, - _ factory: @escaping () -> T - ) { - lock.lock() - defer { lock.unlock() } - - let key = Key(type: .init(type), name: name) - registrations[key] = Registration(scope: scope, factory: factory) - } - - public func resolve(_ type: T.Type, name: DependencyName? = nil) -> T { - lock.lock() - defer { lock.unlock() } - - let key = Key(type: .init(type), name: name) - guard let registration = registrations[key] else { fatalError("\(type)에 대한 의존성이 등록되지 않았습니다.") } - - switch registration.scope { - case .singleton: - if let cached = singletons[key] as? T { return cached } - guard let singleton = registration.factory() as? T else { fatalError("\(type) 생성 실패") } - singletons[key] = singleton - return singleton - - case .transient: - guard let resolved = registration.factory() as? T else { fatalError("\(type) 생성 실패") } - return resolved - } - } -} diff --git a/Application/Core/Sources/DIContainerKey.swift b/Application/Core/Sources/DIContainerKey.swift deleted file mode 100644 index 39e0c674..00000000 --- a/Application/Core/Sources/DIContainerKey.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// DIContainerKey.swift -// Core -// -// Created by opfic on 5/15/26. -// - -import SwiftUI - -private struct DIContainerKey: EnvironmentKey { - static let defaultValue: any DIContainer = AppDIContainer.shared -} - -public extension EnvironmentValues { - var diContainer: any DIContainer { - get { self[DIContainerKey.self] } - set { self[DIContainerKey.self] = newValue } - } -} diff --git a/Application/Data/Sources/DataAssembler.swift b/Application/Data/Sources/DataAssembler.swift deleted file mode 100644 index 5f3a1e51..00000000 --- a/Application/Data/Sources/DataAssembler.swift +++ /dev/null @@ -1,161 +0,0 @@ -// -// DataAssembler.swift -// Data -// -// Created by 최윤진 on 12/7/25. -// - -import Core -import Domain - -public final class DataAssembler: Assembler { - public init() { } - - public func assemble(_ container: any DIContainer) { - container.register(AuthenticationRepository.self) { - AuthenticationRepositoryImpl( - authService: container.resolve(AuthService.self), - appleAuthService: container.resolve( - AppleAuthenticationService.self, - name: "AppleAuthenticationService" - ), - githubAuthService: container.resolve( - GithubAuthenticationService.self, - name: "GithubAuthenticationService" - ), - googleAuthService: container.resolve( - GoogleAuthenticationService.self, - name: "GoogleAuthenticationService" - ), - userService: container.resolve(UserService.self), - widgetSnapshotUpdater: container.resolve(WidgetSnapshotUpdater.self) - ) - } - - container.register(TodoMutationEventBus.self) { - TodoMutationEventBusImpl() - } - - container.register(DevelopmentGoalRepository.self) { - DevelopmentGoalRepositoryImpl( - service: container.resolve(DevelopmentGoalService.self) - ) - } - - container.register(DevelopmentRecordRepository.self) { - DevelopmentRecordRepositoryImpl( - service: container.resolve(DevelopmentRecordService.self) - ) - } - - container.register(TodoRepository.self) { - TodoRepositoryImpl( - queryService: container.resolve(TodoQueryService.self), - commandService: container.resolve(TodoCommandService.self), - todoCategoryService: container.resolve(TodoCategoryService.self), - store: container.resolve(MemoryCacheStore.self), - updater: container.resolve(WidgetSnapshotUpdater.self), - eventBus: container.resolve(TodoMutationEventBus.self) - ) - } - - container.register(WidgetTodoSnapshotRepository.self) { - WidgetTodoSnapshotRepositoryImpl(queryService: container.resolve(TodoQueryService.self)) - } - - container.register(TodoCategoryRepository.self) { - TodoCategoryRepositoryImpl( - todoCategoryService: container.resolve(TodoCategoryService.self), - store: container.resolve(MemoryCacheStore.self) - ) - } - - container.register(AuthSessionRepository.self) { - AuthSessionRepositoryImpl( - authService: container.resolve(AuthService.self), - todoCategoryService: container.resolve(TodoCategoryService.self), - store: container.resolve(MemoryCacheStore.self), - provider: container.resolve(AuthSessionStateProvider.self) - ) - } - - container.register(NetworkConnectivityRepository.self) { - NetworkConnectivityRepositoryImpl( - connectivityProvider: container.resolve(NWPathConnectivityProvider.self) - ) - } - - container.register(AppVersionRepository.self) { - AppVersionRepositoryImpl( - service: container.resolve(AppStoreVersionService.self) - ) - } - - container.register(AuthDataRepository.self) { - AuthDataRepositoryImpl( - authService: container.resolve(AuthService.self), - appleAuthService: container.resolve( - AppleAuthenticationService.self, - name: "AppleAuthenticationService" - ), - githubAuthService: container.resolve( - GithubAuthenticationService.self, - name: "GithubAuthenticationService" - ), - googleAuthService: container.resolve( - GoogleAuthenticationService.self, - name: "GoogleAuthenticationService" - ) - ) - } - - container.register(UserDataRepository.self) { - UserDataRepositoryImpl(userService: container.resolve(UserService.self)) - } - - container.register(ProfileImageDataRepository.self) { - ProfileImageDataRepositoryImpl( - service: container.resolve(ProfileImageDataService.self), - store: container.resolve(MemoryCacheStore.self) - ) - } - - container.register(AnalyticsRepository.self) { - AnalyticsRepositoryImpl( - analyticsService: container.resolve(AnalyticsService.self) - ) - } - - container.register(PushNotificationRepository.self) { - PushNotificationRepositoryImpl( - pushNotificationService: container.resolve(PushNotificationService.self), - todoCategoryService: container.resolve(TodoCategoryService.self), - store: container.resolve(MemoryCacheStore.self) - ) - } - - container.register(WebPageRepository.self) { - WebPageRepositoryImpl( - authService: container.resolve(AuthService.self), - metadataService: container.resolve(WebPageMetadataService.self), - webPageService: container.resolve(WebPageService.self) - ) - } - - container.register(WebPageImageRepository.self) { - WebPageImageRepositoryImpl( - authService: container.resolve(AuthService.self), - store: container.resolve(WebPageImageStore.self) - ) - } - - container.register(UserPreferencesRepository.self) { - UserPreferencesRepositoryImpl( - store: container.resolve(UserDefaultsStore.self), - themeStore: container.resolve(ThemeStore.self), - widgetSnapshotPreferenceStore: container.resolve(WidgetSnapshotPreferenceStore.self), - widgetSyncEventBus: container.resolve(WidgetSyncEventBus.self) - ) - } - } -} diff --git a/Application/Domain/Sources/DomainAssembler.swift b/Application/Domain/Sources/DomainAssembler.swift deleted file mode 100644 index ffa9465a..00000000 --- a/Application/Domain/Sources/DomainAssembler.swift +++ /dev/null @@ -1,301 +0,0 @@ -// -// DomainAssembler.swift -// Domain -// -// Created by 최윤진 on 12/7/25. -// - -import Core - -public final class DomainAssembler: Assembler { - public init() { } - - public func assemble(_ container: any DIContainer) { - registerAnalyticsUseCases(container) - registerAppUpdateUseCases(container) - registerAuthUseCases(container) - registerConnectivityUseCases(container) - registerAuthProviderUseCases(container) - registerDevelopmentGoalUseCases(container) - registerDevelopmentRecordUseCases(container) - registerTodoUseCases(container) - registerTodoCategoryUseCases(container) - registerUserDataUseCases(container) - registerPushNotificationUseCases(container) - registerWebPageUseCases(container) - registerUserPreferencesUseCases(container) - } -} - -private extension DomainAssembler { - func registerDevelopmentGoalUseCases(_ container: any DIContainer) { - container.register(CreateDevelopmentGoalUseCase.self) { - CreateDevelopmentGoalUseCaseImpl(container.resolve(DevelopmentGoalRepository.self)) - } - - container.register(FetchDevelopmentGoalUseCase.self) { - FetchDevelopmentGoalUseCaseImpl(container.resolve(DevelopmentGoalRepository.self)) - } - - container.register(FetchDevelopmentGoalsUseCase.self) { - FetchDevelopmentGoalsUseCaseImpl(container.resolve(DevelopmentGoalRepository.self)) - } - - container.register(UpdateDevelopmentGoalStatusUseCase.self) { - UpdateDevelopmentGoalStatusUseCaseImpl( - container.resolve(DevelopmentGoalRepository.self) - ) - } - } - - func registerDevelopmentRecordUseCases(_ container: any DIContainer) { - container.register(CreateDevelopmentRecordUseCase.self) { - CreateDevelopmentRecordUseCaseImpl( - container.resolve(DevelopmentRecordRepository.self), - container.resolve(DevelopmentGoalRepository.self) - ) - } - - container.register(FetchDevelopmentRecordsUseCase.self) { - FetchDevelopmentRecordsUseCaseImpl(container.resolve(DevelopmentRecordRepository.self)) - } - - container.register(FetchDevelopmentRecordHistoryUseCase.self) { - FetchDevelopmentRecordHistoryUseCaseImpl( - container.resolve(DevelopmentRecordRepository.self) - ) - } - - container.register(SaveDevelopmentRecordDraftUseCase.self) { - SaveDevelopmentRecordDraftUseCaseImpl( - container.resolve(DevelopmentRecordRepository.self), - container.resolve(DevelopmentGoalRepository.self) - ) - } - - container.register(ConfirmDevelopmentRecordUseCase.self) { - ConfirmDevelopmentRecordUseCaseImpl( - container.resolve(DevelopmentRecordRepository.self), - container.resolve(DevelopmentGoalRepository.self) - ) - } - - container.register(RestoreDevelopmentRecordUseCase.self) { - RestoreDevelopmentRecordUseCaseImpl( - container.resolve(DevelopmentRecordRepository.self), - container.resolve(DevelopmentGoalRepository.self) - ) - } - } - - func registerAppUpdateUseCases(_ container: any DIContainer) { - container.register(CheckAppUpdateUseCase.self) { - CheckAppUpdateUseCaseImpl(container.resolve(AppVersionRepository.self)) - } - } - - func registerAnalyticsUseCases(_ container: any DIContainer) { - container.register(TrackAnalyticsEventUseCase.self) { - TrackAnalyticsEventUseCaseImpl(container.resolve(AnalyticsRepository.self)) - } - } - - func registerAuthUseCases(_ container: any DIContainer) { - container.register(SignInUseCase.self) { - SignInUseCaseImpl(container.resolve(AuthenticationRepository.self)) - } - - container.register(SignOutUseCase.self) { - SignOutUseCaseImpl(container.resolve(AuthenticationRepository.self)) - } - - container.register(DeleteAuthUseCase.self) { - DeleteAuthUseCaseImpl(container.resolve(AuthenticationRepository.self)) - } - - container.register(ObserveAuthSessionUseCase.self) { - ObserveAuthSessionUseCaseImpl(container.resolve(AuthSessionRepository.self)) - } - } - - func registerConnectivityUseCases(_ container: any DIContainer) { - container.register(ObserveNetworkConnectivityUseCase.self) { - ObserveNetworkConnectivityUseCaseImpl( - container.resolve(NetworkConnectivityRepository.self) - ) - } - } - - func registerAuthProviderUseCases(_ container: any DIContainer) { - container.register(FetchAuthProvidersUseCase.self) { - FetchAuthProvidersUseCaseImpl(container.resolve(AuthDataRepository.self)) - } - - container.register(LinkAuthProviderUseCase.self) { - LinkAuthProviderUseCaseImpl(container.resolve(AuthDataRepository.self)) - } - - container.register(UnlinkAuthProviderUseCase.self) { - UnlinkAuthProviderUseCaseImpl(container.resolve(AuthDataRepository.self)) - } - } - - func registerTodoUseCases(_ container: any DIContainer) { - container.register(FetchTodoByIdUseCase.self) { - FetchTodoByIdUseCaseImpl(container.resolve(TodoRepository.self)) - } - - container.register(FetchReferenceItemsUseCase.self) { - FetchReferenceItemsUseCaseImpl(container.resolve(TodoRepository.self)) - } - - container.register(FetchTodosUseCase.self) { - FetchTodosUseCaseImpl(container.resolve(TodoRepository.self)) - } - - container.register(UpsertTodoUseCase.self) { - UpsertTodoUseCaseImpl(container.resolve(TodoRepository.self)) - } - - container.register(DeleteTodoUseCase.self) { - DeleteTodoUseCaseImpl(container.resolve(TodoRepository.self)) - } - - container.register(UndoDeleteTodoUseCase.self) { - UndoDeleteTodoUseCaseImpl(container.resolve(TodoRepository.self)) - } - - container.register(UpdateTodoGoalUseCase.self) { - UpdateTodoGoalUseCaseImpl( - container.resolve(TodoRepository.self), - container.resolve(DevelopmentGoalRepository.self) - ) - } - } - - func registerTodoCategoryUseCases(_ container: any DIContainer) { - container.register(FetchTodoCategoryPreferencesUseCase.self) { - FetchTodoCategoryPreferencesUseCaseImpl( - container.resolve(TodoCategoryRepository.self) - ) - } - - container.register(UpdateTodoCategoryPreferencesUseCase.self) { - UpdateTodoCategoryPreferencesUseCaseImpl( - container.resolve(TodoCategoryRepository.self) - ) - } - } - - func registerUserDataUseCases(_ container: any DIContainer) { - container.register(FetchUserDataUseCase.self) { - FetchUserDataUseCaseImpl(container.resolve(UserDataRepository.self)) - } - - container.register(FetchProfileImageDataUseCase.self) { - FetchProfileImageDataUseCaseImpl(container.resolve(ProfileImageDataRepository.self)) - } - - container.register(UpsertStatusMessageUseCase.self) { - UpsertStatusMessageUseCaseImpl(container.resolve(UserDataRepository.self)) - } - } - - func registerPushNotificationUseCases(_ container: any DIContainer) { - container.register(FetchPushSettingsUseCase.self) { - FetchPushSettingsUseCaseImpl(container.resolve(PushNotificationRepository.self)) - } - - container.register(UpdatePushSettingsUseCase.self) { - UpdatePushSettingsUseCaseImpl(container.resolve(PushNotificationRepository.self)) - } - - container.register(DeletePushNotificationUseCase.self) { - DeletePushNotificationUseCaseImpl(container.resolve(PushNotificationRepository.self)) - } - - container.register(UndoDeletePushNotificationUseCase.self) { - UndoDeletePushNotificationUseCaseImpl(container.resolve(PushNotificationRepository.self)) - } - - container.register(FetchPushNotificationsUseCase.self) { - FetchPushNotificationsUseCaseImpl(container.resolve(PushNotificationRepository.self)) - } - - container.register(ObserveUnreadPushCountUseCase.self) { - ObserveUnreadPushCountUseCaseImpl(container.resolve(PushNotificationRepository.self)) - } - - container.register(TogglePushNotificationReadUseCase.self) { - TogglePushNotificationReadUseCaseImpl(container.resolve(PushNotificationRepository.self)) - } - } - - func registerWebPageUseCases(_ container: any DIContainer) { - container.register(FetchWebPagesUseCase.self) { - FetchWebPagesUseCaseImpl(container.resolve(WebPageRepository.self)) - } - - container.register(FetchWebPageImageDirSizeUseCase.self) { - FetchWebPageImageDirSizeUseCaseImpl(container.resolve(WebPageImageRepository.self)) - } - - container.register(AddWebPageUseCase.self) { - AddWebPageUseCaseImpl(container.resolve(WebPageRepository.self)) - } - - container.register(ClearWebPageImageDirectoryUseCase.self) { - ClearWebPageImageDirectoryUseCaseImpl(container.resolve(WebPageImageRepository.self)) - } - - container.register(DeleteWebPageUseCase.self) { - DeleteWebPageUseCaseImpl(container.resolve(WebPageRepository.self)) - } - - container.register(UndoDeleteWebPageUseCase.self) { - UndoDeleteWebPageUseCaseImpl(container.resolve(WebPageRepository.self)) - } - } - - func registerUserPreferencesUseCases(_ container: any DIContainer) { - container.register(ObserveSystemThemeUseCase.self) { - ObserveSystemThemeUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(UpdateSystemThemeUseCase.self) { - UpdateSystemThemeUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(FetchRecentSearchQueriesUseCase.self) { - FetchRecentSearchQueriesUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(UpdateRecentSearchQueriesUseCase.self) { - UpdateRecentSearchQueriesUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(FetchPushNotificationQueryUseCase.self) { - FetchPushNotificationQueryUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(UpdatePushNotificationQueryUseCase.self) { - UpdatePushNotificationQueryUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(FetchHeatmapActivityTypesUseCase.self) { - FetchHeatmapActivityTypesUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(UpdateHeatmapActivityTypesUseCase.self) { - UpdateHeatmapActivityTypesUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(FetchTodayDisplayOptionsUseCase.self) { - FetchTodayDisplayOptionsUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - - container.register(UpdateTodayDisplayOptionsUseCase.self) { - UpdateTodayDisplayOptionsUseCaseImpl(container.resolve(UserPreferencesRepository.self)) - } - } -} diff --git a/Application/Infra/Sources/InfraAssembler.swift b/Application/Infra/Sources/InfraAssembler.swift deleted file mode 100644 index c59d8d62..00000000 --- a/Application/Infra/Sources/InfraAssembler.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// InfraAssembler.swift -// Infra -// -// Created by 최윤진 on 12/7/25. -// - -import Core -import Data - -public final class InfraAssembler: Assembler { - public init() { } - - public func assemble(_ container: any DIContainer) { - container.register(FirebaseAppService.self) { - FirebaseAppServiceImpl() - } - - container.register(AppStoreVersionService.self) { - ITunesAppVersionServiceImpl() - } - - container.register(AnalyticsService.self) { - FirebaseAnalyticsServiceImpl() - } - - container.register(PushMessagingService.self) { - PushMessagingServiceImpl() - } - - container.register( - AppleAuthenticationService.self, - name: "AppleAuthenticationService" - ) { - AppleAuthenticationServiceImpl() - } - - container.register( - GithubAuthenticationService.self, - name: "GithubAuthenticationService" - ) { - GithubAuthenticationServiceImpl() - } - - container.register( - GoogleAuthenticationService.self, - name: "GoogleAuthenticationService" - ) { - GoogleAuthenticationServiceImpl() - } - - container.register(AuthService.self) { - AuthServiceImpl() - } - - container.register(TodoQueryService.self) { - TodoQueryServiceImpl() - } - - container.register(TodoCommandService.self) { - TodoCommandServiceImpl() - } - - container.register(DevelopmentGoalService.self) { - DevelopmentGoalServiceImpl() - } - - container.register(DevelopmentRecordService.self) { - DevelopmentRecordServiceImpl() - } - - container.register(TodoCategoryService.self) { - TodoCategoryServiceImpl() - } - - container.register(UserService.self) { - UserServiceImpl() - } - - container.register(ProfileImageDataService.self) { - ProfileImageDataServiceImpl() - } - - container.register(PushNotificationService.self) { - PushNotificationServiceImpl() - } - - container.register(WebPageService.self) { - WebPageServiceImpl() - } - - container.register(WebPageMetadataService.self) { - WebPageMetadataServiceImpl( - store: container.resolve(WebPageImageStore.self) - ) - } - - container.register(NWPathConnectivityProvider.self) { - NWPathConnectivityProviderImpl() - } - } -} diff --git a/Application/Persistence/Sources/PersistenceAssembler.swift b/Application/Persistence/Sources/PersistenceAssembler.swift deleted file mode 100644 index 7e55aad5..00000000 --- a/Application/Persistence/Sources/PersistenceAssembler.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// PersistenceAssembler.swift -// Persistence -// -// Created by opfic on 3/15/26. -// - -import Core -import Data - -public final class PersistenceAssembler: Assembler { - public init() { } - - public func assemble(_ container: any DIContainer) { - container.register(UserDefaultsStore.self) { - UserDefaultsStoreImpl() - } - - container.register(MemoryCacheStore.self) { - MemoryCacheStoreImpl() - } - - container.register(ThemeStore.self) { - ThemeStoreImpl() - } - - container.register(WebPageImageStore.self) { - WebPageImageStoreImpl() - } - } -} diff --git a/Application/Widget/Sources/Widget/WidgetAssembler.swift b/Application/Widget/Sources/Widget/WidgetAssembler.swift deleted file mode 100644 index 7323f8df..00000000 --- a/Application/Widget/Sources/Widget/WidgetAssembler.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// WidgetAssembler.swift -// Widget -// -// Created by opfic on 6/8/26. -// - -import Core -import Data -import WidgetCore - -public final class WidgetAssembler: Assembler { - public init() { } - - public func assemble(_ container: any DIContainer) { - container.register(AuthSessionStateProvider.self) { - AuthSessionStateProviderImpl() - } - - container.register(WidgetSyncEventBus.self) { - WidgetSyncEventBusImpl() - } - container.register(WidgetSharedDefaultsStore.self) { - WidgetSharedDefaultsStore() - } - container.register(WidgetSnapshotStore.self) { - WidgetSnapshotStore( - store: container.resolve(WidgetSharedDefaultsStore.self) - ) - } - container.register(WidgetSnapshotPreferenceStore.self) { - WidgetSnapshotPreferenceStoreImpl() - } - container.register(WidgetSnapshotUpdater.self) { - WidgetSnapshotUpdaterImpl( - snapshotStore: container.resolve(WidgetSnapshotStore.self), - preferenceStore: container.resolve(WidgetSnapshotPreferenceStore.self) - ) - } - container.register(WidgetSyncEventHandler.self) { - WidgetSyncEventHandler( - eventBus: container.resolve(WidgetSyncEventBus.self), - repository: container.resolve(WidgetTodoSnapshotRepository.self), - snapshotUpdater: container.resolve(WidgetSnapshotUpdater.self) - ) - } - container.register(WidgetSessionSyncHandler.self) { - WidgetSessionSyncHandler( - provider: container.resolve(AuthSessionStateProvider.self), - widgetSyncEventBus: container.resolve(WidgetSyncEventBus.self) - ) - } - } -} diff --git a/README.md b/README.md index b94d5781..7af41d9a 100644 --- a/README.md +++ b/README.md @@ -239,8 +239,8 @@ DevLog_iOS/ ├── Tuist/ │ └── ProjectDescriptionHelpers/ # Tuist 공통 패키지, 설정, 타깃 템플릿 ├── Application/ -│ ├── App/ # 앱 진입점, 앱 생명주기, 라우팅, Assembler 구성 -│ ├── Core/ # DI, Logger, Query, 공통 값 타입 +│ ├── App/ # 앱 진입점, 앱 생명주기, 라우팅, Cradle graph 조립 +│ ├── Core/ # Logger, Query, 공통 값 타입 │ ├── Domain/ # Entity, Repository Protocol, UseCase │ ├── Data/ # Repository 구현, DTO, Mapper, Data 계층 Protocol │ ├── Infra/ # Firebase, 소셜 로그인, 네트워크, 메타데이터 서비스 구현 From abf584a24641958a5196ed1a452a115f752c7f5f Mon Sep 17 00:00:00 2001 From: opficdev Date: Mon, 7 Sep 2026 22:35:04 +0900 Subject: [PATCH 19/19] =?UTF-8?q?ci:=20Cradle=20=EB=8F=84=EA=B5=AC=20?= =?UTF-8?q?=EB=B2=84=EC=A0=84=20=EB=8C=80=EC=9D=91=20Xcode=20=EC=83=81?= =?UTF-8?q?=ED=96=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 763397b6..b417fec0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: env: WORKSPACE: DevLog.xcworkspace SCHEME: App - XCODE_VERSION: "26.3" + XCODE_VERSION: "26.5" MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }}