From 324496aa305c31956918b396a2393b17d951f394 Mon Sep 17 00:00:00 2001 From: iceHood Date: Mon, 25 Nov 2024 16:51:39 +0900 Subject: [PATCH 01/44] =?UTF-8?q?feat:=20Page=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHDomain/Entity/MediaDescription.swift | 14 ++++++++++++++ .../MHDomain/MHDomain/Entity/MediaType.swift | 5 +++++ .../MHDomain/MHDomain/Entity/Page.swift | 17 +++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift create mode 100644 MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift create mode 100644 MemorialHouse/MHDomain/MHDomain/Entity/Page.swift diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift b/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift new file mode 100644 index 00000000..d943dcd1 --- /dev/null +++ b/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift @@ -0,0 +1,14 @@ +import Foundation + +public struct MediaDescription: Identifiable { + public let id: UUID + public let type: MediaType + + public init( + id: UUID, + type: MediaType + ) { + self.id = id + self.type = type + } +} diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift b/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift new file mode 100644 index 00000000..041527b1 --- /dev/null +++ b/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift @@ -0,0 +1,5 @@ +public enum MediaType { + case image + case video + case audio +} diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift b/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift new file mode 100644 index 00000000..8c8effba --- /dev/null +++ b/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift @@ -0,0 +1,17 @@ +import Foundation + +public struct Page: Identifiable { + public let id: UUID + public let metadata: [Int: MediaDescription] + public let text: String + + public init( + id: UUID, + metadata: [Int : MediaDescription], + text: String + ) { + self.id = id + self.metadata = metadata + self.text = text + } +} From 2d77243ae0847476a2efba07df3dc03d49297152 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 09:48:21 +0900 Subject: [PATCH 02/44] =?UTF-8?q?chore:=20Page=20=EB=A6=B0=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHDomain/MHDomain/Entity/Page.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift b/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift index 8c8effba..90ea8a76 100644 --- a/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift +++ b/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift @@ -7,7 +7,7 @@ public struct Page: Identifiable { public init( id: UUID, - metadata: [Int : MediaDescription], + metadata: [Int: MediaDescription], text: String ) { self.id = id From 0095076930c37b1d1ab660f5370f4e35c01e111c Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 09:48:32 +0900 Subject: [PATCH 03/44] =?UTF-8?q?feat:=20Book=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHDomain/MHDomain/Entity/Book.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 MemorialHouse/MHDomain/MHDomain/Entity/Book.swift diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift b/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift new file mode 100644 index 00000000..75484145 --- /dev/null +++ b/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift @@ -0,0 +1,13 @@ +import Foundation + +public struct Book: Identifiable { + public let id: UUID + public let index: [Int] + public let pages: [Page] + + public init(id: UUID, index: [Int], pages: [Page]) { + self.id = id + self.index = index + self.pages = pages + } +} From ec3fcc95a6b2ab47e5fd463e01c5129c5c1e7781 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 09:52:34 +0900 Subject: [PATCH 04/44] =?UTF-8?q?refactor:=20Entity=20=EA=B8=B0=EC=A1=B4?= =?UTF-8?q?=20=EC=BB=A8=EB=B2=A4=EC=85=98=EC=97=90=20=EB=A7=9E=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHDomain/MHDomain/Entity/Book.swift | 8 ++++++-- .../MHDomain/MHDomain/Entity/MediaDescription.swift | 4 ++-- MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift | 2 +- MemorialHouse/MHDomain/MHDomain/Entity/Page.swift | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift b/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift index 75484145..65526068 100644 --- a/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift +++ b/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift @@ -1,11 +1,15 @@ import Foundation -public struct Book: Identifiable { +public struct Book: Identifiable, Sendable { public let id: UUID public let index: [Int] public let pages: [Page] - public init(id: UUID, index: [Int], pages: [Page]) { + public init( + id: UUID = .init(), + index: [Int], + pages: [Page] + ) { self.id = id self.index = index self.pages = pages diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift b/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift index d943dcd1..63627fc4 100644 --- a/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift +++ b/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift @@ -1,11 +1,11 @@ import Foundation -public struct MediaDescription: Identifiable { +public struct MediaDescription: Identifiable, Sendable { public let id: UUID public let type: MediaType public init( - id: UUID, + id: UUID = .init(), type: MediaType ) { self.id = id diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift b/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift index 041527b1..5a30b22d 100644 --- a/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift +++ b/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift @@ -1,4 +1,4 @@ -public enum MediaType { +public enum MediaType: Sendable { case image case video case audio diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift b/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift index 90ea8a76..6af5aa50 100644 --- a/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift +++ b/MemorialHouse/MHDomain/MHDomain/Entity/Page.swift @@ -1,12 +1,12 @@ import Foundation -public struct Page: Identifiable { +public struct Page: Identifiable, Sendable { public let id: UUID public let metadata: [Int: MediaDescription] public let text: String public init( - id: UUID, + id: UUID = .init(), metadata: [Int: MediaDescription], text: String ) { From 0da53c1d5bf1b9e0c2eecc0500a8eb12c9ffc4d7 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 14:05:25 +0900 Subject: [PATCH 05/44] =?UTF-8?q?refactor:=20MediaType=EC=9D=B4=20String?= =?UTF-8?q?=EC=9D=84=20rawValue=EB=A1=9C=20=EA=B0=80=EC=A7=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift b/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift index 5a30b22d..e2dad1f2 100644 --- a/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift +++ b/MemorialHouse/MHDomain/MHDomain/Entity/MediaType.swift @@ -1,4 +1,4 @@ -public enum MediaType: Sendable { +public enum MediaType: String, Sendable { case image case video case audio From cad4f143da8dc438eb9740e8b06e3be02647df3d Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 14:05:53 +0900 Subject: [PATCH 06/44] =?UTF-8?q?feat:=20=EC=B6=94=ED=9B=84=20CoreData?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=9C=20DTO=EC=B6=94=EC=83=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHData/MHData/DTO/BookDTO.swift | 16 ++++++++++++++++ .../MHData/DTO/MediaDescriptionDTO.swift | 17 +++++++++++++++++ MemorialHouse/MHData/MHData/DTO/PageDTO.swift | 19 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 MemorialHouse/MHData/MHData/DTO/BookDTO.swift create mode 100644 MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift create mode 100644 MemorialHouse/MHData/MHData/DTO/PageDTO.swift diff --git a/MemorialHouse/MHData/MHData/DTO/BookDTO.swift b/MemorialHouse/MHData/MHData/DTO/BookDTO.swift new file mode 100644 index 00000000..eff02523 --- /dev/null +++ b/MemorialHouse/MHData/MHData/DTO/BookDTO.swift @@ -0,0 +1,16 @@ +import MHFoundation +import MHDomain + +public struct BookDTO { + let id: UUID + let index: [Int] + let pages: [PageDTO] + + func toBook() -> Book { + return Book( + id: self.id, + index: self.index, + pages: self.pages.map { $0.toPage() } + ) + } +} diff --git a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift new file mode 100644 index 00000000..cbe165ce --- /dev/null +++ b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift @@ -0,0 +1,17 @@ +import MHFoundation +import MHDomain + + +public struct MediaDescriptionDTO { + let id: UUID + let type: String + + func toMediaDescription() -> MediaDescription? { + guard let type = MediaType(rawValue: self.type) else { return nil } + + return MediaDescription( + id: self.id, + type: type + ) + } +} diff --git a/MemorialHouse/MHData/MHData/DTO/PageDTO.swift b/MemorialHouse/MHData/MHData/DTO/PageDTO.swift new file mode 100644 index 00000000..c60be3a8 --- /dev/null +++ b/MemorialHouse/MHData/MHData/DTO/PageDTO.swift @@ -0,0 +1,19 @@ +import MHFoundation +import MHDomain + +public struct PageDTO { + let id: UUID + let metadata: [Int: MediaDescriptionDTO] + let text: String + + func toPage() -> Page { + let metadata = self.metadata + .compactMapValues { $0.toMediaDescription() } + + return Page( + id: self.id, + metadata: metadata, + text: self.text + ) + } +} From 44043565f366e86d1f163687ed0db17db32cf454 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 14:06:15 +0900 Subject: [PATCH 07/44] =?UTF-8?q?feat:=20Book,=20Page=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=EC=A7=80=20CRUD=20=ED=94=84=EB=A1=9C=ED=86=A0?= =?UTF-8?q?=EC=BD=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/MHData/LocalStorage/BookStorage.swift | 9 +++++++++ .../MHData/MHData/LocalStorage/PageStorage.swift | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift create mode 100644 MemorialHouse/MHData/MHData/LocalStorage/PageStorage.swift diff --git a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift new file mode 100644 index 00000000..58b13d25 --- /dev/null +++ b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift @@ -0,0 +1,9 @@ +import MHFoundation +import MHCore + +public protocol PageStrorage { + func create(data: PageDTO) async -> Result + func fetch() async -> Result<[PageDTO], MHError> + func update(with id: UUID, data: PageDTO) async -> Result + func delete(with id: UUID) async -> Result +} diff --git a/MemorialHouse/MHData/MHData/LocalStorage/PageStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/PageStorage.swift new file mode 100644 index 00000000..e81dfd44 --- /dev/null +++ b/MemorialHouse/MHData/MHData/LocalStorage/PageStorage.swift @@ -0,0 +1,9 @@ +import MHFoundation +import MHCore + +public protocol BookStorage { + func create(data: BookDTO) async -> Result + func fetch() async -> Result<[BookDTO], MHError> + func update(with id: UUID, data: BookDTO) async -> Result + func delete(with id: UUID) async -> Result +} From 1c0745da1c8bb69b9b22ba6d781e2b1e7ca6481c Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:13:33 +0900 Subject: [PATCH 08/44] =?UTF-8?q?feat:=20CoreData=EC=97=90=20Book=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MemorialHouseModel.xcdatamodel/contents | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents index da5aa3d8..ea5c063b 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -8,4 +8,9 @@ + + + + + \ No newline at end of file From 08781ec909b4da54cded274b57c31c29da7ea2bd Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:14:03 +0900 Subject: [PATCH 09/44] =?UTF-8?q?feat:=20BookRepository=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/LocalBookRepository.swift | 62 +++++++++++++++++++ .../MHDomain/Repository/BookRepository.swift | 8 +++ 2 files changed, 70 insertions(+) create mode 100644 MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift create mode 100644 MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift diff --git a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift new file mode 100644 index 00000000..7ee5c766 --- /dev/null +++ b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift @@ -0,0 +1,62 @@ +import MHFoundation +import MHDomain +import MHCore + +public struct LocalBookRepository: BookRepository { + private let storage: BookStorage + + public init(storage: BookStorage) { + self.storage = storage + } + + public func create(book: Book) async { + let bookDTO = mappingBookToDTO(book) + + _ = await storage.create(data: bookDTO) + } + public func fetchBook(with id: UUID) async -> Book? { + let result = await storage.fetch() + + switch result { + case .success(let bookDTO): + return bookDTO.toBook() + case .failure(let failure): + MHLogger.debug("\(failure.description)") + } + + return nil + } + public func update(id: UUID, book: Book) async { + let bookDTO = mappingBookToDTO(book) + + _ = await storage.update(with: id, data: bookDTO) + } + public func deleteBook(_ id: UUID) async { + _ = await storage.delete(with: id) + } + + private func mappingBookToDTO(_ book: Book) -> BookDTO { + let pages = book.pages.map { mappingPageToDTO($0) } + return BookDTO( + id: book.id, + index: book.index, + pages: pages + ) + } + private func mappingPageToDTO(_ page: Page) -> PageDTO { + let meatadata = page.metadata + .compactMapValues { mappingMediaDescriptionToDTO($0) } + + return PageDTO( + id: page.id, + metadata: meatadata, + text: page.text + ) + } + private func mappingMediaDescriptionToDTO(_ description: MediaDescription) -> MediaDescriptionDTO { + return MediaDescriptionDTO( + id: description.id, + type: description.type.rawValue + ) + } +} diff --git a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift new file mode 100644 index 00000000..6b999011 --- /dev/null +++ b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift @@ -0,0 +1,8 @@ +import MHFoundation + +public protocol BookRepository { + func create(book: Book) async + func fetchBook(with id: UUID) async -> Book? + func update(id: UUID, book: Book) async + func deleteBook(_ id: UUID) async +} From 26d3b484a7c3d08f2b971c6e8f3b7f748e0871cf Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:14:44 +0900 Subject: [PATCH 10/44] =?UTF-8?q?refactor:=20PageStroage=20=EC=97=86?= =?UTF-8?q?=EC=96=B4=EB=8F=84=20=EB=90=A0=EB=93=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/MHData/LocalStorage/PageStorage.swift | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 MemorialHouse/MHData/MHData/LocalStorage/PageStorage.swift diff --git a/MemorialHouse/MHData/MHData/LocalStorage/PageStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/PageStorage.swift deleted file mode 100644 index e81dfd44..00000000 --- a/MemorialHouse/MHData/MHData/LocalStorage/PageStorage.swift +++ /dev/null @@ -1,9 +0,0 @@ -import MHFoundation -import MHCore - -public protocol BookStorage { - func create(data: BookDTO) async -> Result - func fetch() async -> Result<[BookDTO], MHError> - func update(with id: UUID, data: BookDTO) async -> Result - func delete(with id: UUID) async -> Result -} From d680ab2893be2d9f8d6d1a4613a1f947bbc4d23a Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:15:20 +0900 Subject: [PATCH 11/44] =?UTF-8?q?feat:=20=ED=8C=8C=EC=9D=BC=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20Storage-MHFileManager=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FileManager/MHFileManager.swift | 83 +++++++++++++++++++ .../MHData/LocalStorage/FileStorage.swift | 9 ++ 2 files changed, 92 insertions(+) create mode 100644 MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift create mode 100644 MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift new file mode 100644 index 00000000..fbdd116d --- /dev/null +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift @@ -0,0 +1,83 @@ +import MHFoundation +import MHCore +import MHDomain + +public struct MHFileManager { + private let fileManager = FileManager.default + private let directoryType: FileManager.SearchPathDirectory +} + +extension MHFileManager: FileStorage { + func create(at path: String, fileName name: String, data: Data) async -> Result { + guard let directory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: path) + else { return .failure(.directorySettingError) } + + let dataPath = directory.appendingPathComponent(name) + + do { + try fileManager.createDirectory(at: directory, withIntermediateDirectories: false) + try data.write(to: dataPath) + return .success(()) + } catch { + return .failure(.fileCreationError) + } + } + func read(at path: String, fileName name: String) async -> Result { + guard let directory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: path) + else { return .failure(.directorySettingError) } + + let dataPath = directory.appendingPathComponent(name) + + do { + return .success(try Data(contentsOf: dataPath)) + } catch { + return .failure(.fileReadingError) + } + } + func delete(at path: String, fileName name: String) async -> Result { + guard let directory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: path) + else { return .failure(.directorySettingError) } + + let dataPath = directory.appendingPathComponent(name) + + do { + try fileManager.removeItem(at: dataPath) + return .success(()) + } catch { + return .failure(.fileDeletionError) + } + } + func move(at path: String, fileName name: String, to newPath: String) async -> Result { + guard let originDirectory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: path) + else { return .failure(.directorySettingError) } + + let originDataPath = originDirectory.appendingPathComponent(name) + + guard let newDirectory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: newPath) + else { return .failure(.directorySettingError) } + + let newDataPath = newDirectory.appendingPathComponent(name) + + do { + try fileManager.moveItem(at: originDataPath, to: newDataPath) + return .success(()) + } catch { + return .failure(.fileMovingError) + } + } +} diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift new file mode 100644 index 00000000..44f937c7 --- /dev/null +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift @@ -0,0 +1,9 @@ +import MHFoundation +import MHCore + +protocol FileStorage { + func create(at path: String, fileName name: String, data: Data) async -> Result + func read(at path: String, fileName name: String) async -> Result + func delete(at path: String, fileName name: String) async -> Result + func move(at path: String, fileName name: String, to newPath: String) async -> Result +} From 464ffc49967bc68f03fe7682d60abc4267ed3b84 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:15:39 +0900 Subject: [PATCH 12/44] =?UTF-8?q?feat:=20BookStroage=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/LocalStorage/BookStorage.swift | 8 +- .../CoreData/CoreDataBookStorage.swift | 94 +++++++++++++++++++ 2 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift diff --git a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift index 58b13d25..4b02fc56 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift @@ -1,9 +1,9 @@ import MHFoundation import MHCore -public protocol PageStrorage { - func create(data: PageDTO) async -> Result - func fetch() async -> Result<[PageDTO], MHError> - func update(with id: UUID, data: PageDTO) async -> Result +public protocol BookStorage { + func create(data: BookDTO) async -> Result + func fetch() async -> Result + func update(with id: UUID, data: BookDTO) async -> Result func delete(with id: UUID) async -> Result } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift new file mode 100644 index 00000000..16390cae --- /dev/null +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -0,0 +1,94 @@ +import MHFoundation +import MHCore +import CoreData + +final class CoreDataBookStorage { + private let coreDataStorage: CoreDataStorage + + init(coreDataStorage: CoreDataStorage) { + self.coreDataStorage = coreDataStorage + } +} + +extension CoreDataBookStorage: BookStorage { + func create(data: BookDTO) async -> Result { + let context = coreDataStorage.persistentContainer.viewContext + guard let entity = NSEntityDescription.entity(forEntityName: "BookEntity", in: context) else { + return .failure(.DIContainerResolveFailure(key: "BookEntity")) + } + + let book = NSManagedObject(entity: entity, insertInto: context) + book.setValue(data.id, forKey: "id") + book.setValue(data.index, forKey: "index") + book.setValue(data.pages, forKey: "pages") + + await coreDataStorage.saveContext() + return .success(()) + } + func fetch() async -> Result { + let context = coreDataStorage.persistentContainer.viewContext + let request = BookEntity.fetchRequest() + + do { + let bookEntity = try context.fetch(request) + guard let result = bookEntity.first?.toBookDTO() + else { throw MHError.convertDTOFailure } + + return .success(result) + } catch { + MHLogger.debug("Error fetching book covers: \(error.localizedDescription)") + return .failure(.convertDTOFailure) + } + } + func update(with id: UUID, data: BookDTO) async -> Result { + do { + let context = coreDataStorage.persistentContainer.viewContext + guard let newEntity = try getEntityByIdentifier(in: context, with: id) else { + return .failure(.findEntityFailure) + } + newEntity.setValue(data.id, forKey: "id") + newEntity.setValue(data.index, forKey: "index") + newEntity.setValue(data.pages, forKey: "pages") + + await coreDataStorage.saveContext() + return .success(()) + } catch { + return .failure(.findEntityFailure) + } + } + func delete(with id: UUID) async -> Result { + do { + let context = coreDataStorage.persistentContainer.viewContext + guard let entity = try getEntityByIdentifier(in: context, with: id) else { + return .failure(.findEntityFailure) + } + + context.delete(entity) + + await coreDataStorage.saveContext() + return .success(()) + } catch { + return .failure(.findEntityFailure) + } + } + + private func getEntityByIdentifier(in context: NSManagedObjectContext, with id: UUID) throws -> BookEntity? { + let request = BookEntity.fetchRequest() + + return try context.fetch(request).first(where: { $0.id == id }) + } +} + +extension BookEntity { + func toBookDTO() -> BookDTO? { + guard let id = self.id, + let index = self.index, + let pages = self.pages else { return nil } + + return BookDTO( + id: id, + index: index, + pages: pages + ) + } +} From fbc49b238b704102d46137af3e1f045c7da02ed4 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:15:50 +0900 Subject: [PATCH 13/44] =?UTF-8?q?feat:=20MHError=EC=9C=A0=ED=98=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHCore/MHCore/MHError.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/MemorialHouse/MHCore/MHCore/MHError.swift b/MemorialHouse/MHCore/MHCore/MHError.swift index c1a12e06..e8f45254 100644 --- a/MemorialHouse/MHCore/MHCore/MHError.swift +++ b/MemorialHouse/MHCore/MHCore/MHError.swift @@ -5,6 +5,11 @@ public enum MHError: Error, CustomStringConvertible, Equatable { case convertDTOFailure case findEntityFailure case saveContextFailure + case directorySettingError + case fileCreationError + case fileReadingError + case fileDeletionError + case fileMovingError public var description: String { switch self { @@ -16,6 +21,16 @@ public enum MHError: Error, CustomStringConvertible, Equatable { "Entity 찾기 실패" case .saveContextFailure: "Update된 Context 저장 실패" + case .directorySettingError: + "디렉토리 설정 실패" + case .fileCreationError: + "파일 생성 실패" + case .fileReadingError: + "파일 읽기 실패" + case .fileDeletionError: + "파일 삭제 실패" + case .fileMovingError: + "파일 이동 실패" } } } From 4b1329c870a15d6132afed76962e5bd64185023b Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:46:40 +0900 Subject: [PATCH 14/44] =?UTF-8?q?refactor:=20Book=EC=9D=84=20id=EB=A1=9C?= =?UTF-8?q?=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B2=8C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift | 2 +- .../MHData/LocalStorage/CoreData/CoreDataBookStorage.swift | 7 ++++++- .../MHData/MHData/Repository/LocalBookRepository.swift | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift index 4b02fc56..b536d295 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift @@ -3,7 +3,7 @@ import MHCore public protocol BookStorage { func create(data: BookDTO) async -> Result - func fetch() async -> Result + func fetch(with id: UUID) async -> Result func update(with id: UUID, data: BookDTO) async -> Result func delete(with id: UUID) async -> Result } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index 16390cae..b7cdf7f9 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -25,9 +25,14 @@ extension CoreDataBookStorage: BookStorage { await coreDataStorage.saveContext() return .success(()) } - func fetch() async -> Result { + func fetch(with id: UUID) async -> Result { let context = coreDataStorage.persistentContainer.viewContext let request = BookEntity.fetchRequest() + + request.predicate = NSPredicate( + format: "id LIKE %@", "\(id.uuidString)" + ) + do { let bookEntity = try context.fetch(request) diff --git a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift index 7ee5c766..355aaee3 100644 --- a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift +++ b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift @@ -15,7 +15,7 @@ public struct LocalBookRepository: BookRepository { _ = await storage.create(data: bookDTO) } public func fetchBook(with id: UUID) async -> Book? { - let result = await storage.fetch() + let result = await storage.fetch(with: id) switch result { case .success(let bookDTO): From 2ee6924b6ab934901c45567c1ee6d18d1691cbdf Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:46:58 +0900 Subject: [PATCH 15/44] =?UTF-8?q?feat:=20Test=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreDataBookStorageTests.swift | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift diff --git a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift new file mode 100644 index 00000000..84398ab6 --- /dev/null +++ b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift @@ -0,0 +1,169 @@ +import Testing +@testable import MHCore +@testable import MHData +@testable import MHDomain +@testable import MHFoundation + +struct CoreDataBookStorageTests { + // MARK: - Properties + private let sut = CoreDataBookStorage(coreDataStorage: MockCoreDataStorage()) + private static let book = BookDTO( + id: UUID(), + index: [], + pages: [ + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "image") + ], + text: "first page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "video") + ], + text: "second page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "audio") + ], + text: "third page" + ) + ] + ) + + init() async { + _ = await sut.create(data: CoreDataBookStorageTests.book) + } + + @Test func test코어데이터에_새로운_Book_객체를_생성한다() async throws { + // Arrange + let newBook = BookDTO( + id: UUID(), + index: [], + pages: [ + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "image") + ], + text: "first page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "video") + ], + text: "second page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "audio") + ], + text: "third page" + ) + ] + ) + + // Act + let result = await sut.create(data: newBook) + let coreDataBook = try await sut.fetch(with: newBook.id).get() + + // Assert + switch result { + case .success: + #expect(coreDataBook.id == newBook.id) + case .failure(let error): + #expect(false, "Create Book 실패: \(error.localizedDescription)") + } + } + + @Test func test코어데이터에_저장된_Book_객체를_불러온다() async { + // Arrange + // Act + let result = await sut.fetch(with: CoreDataBookStorageTests.book.id) + + // Assert + switch result { + case .success(let bookResult): + #expect(CoreDataBookStorageTests.book.id == bookResult.id) + case .failure(let error): + #expect(false, "Fetch Book 실패: \(error.localizedDescription)") + } + } + + @Test func test코어데이터에서_특정_UUID값을_가진_Book_데이터를_업데이트한다() async throws { + // Arrange + let oldBook = CoreDataBookStorageTests.book + let newBook = BookDTO( + id: oldBook.id, + index: [], + pages: [ + PageDTO( + id: oldBook.pages[0].id, + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "image") + ], + text: "first page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "image"), + 2: MediaDescriptionDTO(id: UUID(), type: "image") + ], + text: "second page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "audio") + ], + text: "third page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "video") + ], + text: "fourth page" + ) + ] + ) + + // Act + let result = await sut.update(with: oldBook.id, data: newBook) + let coreDataBook = try await sut.fetch(with: oldBook.id).get() + + // Assert + switch result { + case .success: + let newBookResult = coreDataBook + #expect(newBookResult.pages.count != oldBook.pages.count) + case .failure(let error): + #expect(false, "Update BookCover 실패: \(error.localizedDescription)") + } + } + + @Test(arguments: [CoreDataBookCoverStorageTests.bookCovers[0].identifier, + CoreDataBookCoverStorageTests.bookCovers[1].identifier, + UUID()] + ) func test코어데이터에서_특정_UUID값을_가진_BookCover_데이터를_삭제한다(_ id: UUID) async throws { + // Arrange + // Act + let result = await sut.delete(with: id) + let coreDataBookCovers = try await sut.fetch().get() + + // Assert + switch result { + case .success: + #expect(!coreDataBookCovers.contains(where: { $0.identifier == id })) + case .failure(let error): + #expect(error == MHError.findEntityFailure && !coreDataBookCovers.contains(where: { $0.identifier == id })) + } + } +} From ead3b39ded6c815fec7c78d02b1180d172be00ff Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:56:19 +0900 Subject: [PATCH 16/44] =?UTF-8?q?feat:=20BookStorageTest=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreDataBookStorageTests.swift | 104 +++++++++++------- 1 file changed, 67 insertions(+), 37 deletions(-) diff --git a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift index 84398ab6..05262638 100644 --- a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift +++ b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift @@ -7,36 +7,66 @@ import Testing struct CoreDataBookStorageTests { // MARK: - Properties private let sut = CoreDataBookStorage(coreDataStorage: MockCoreDataStorage()) - private static let book = BookDTO( - id: UUID(), - index: [], - pages: [ - PageDTO( - id: UUID(), - metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "image") - ], - text: "first page" - ), - PageDTO( - id: UUID(), - metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "video") - ], - text: "second page" - ), - PageDTO( - id: UUID(), - metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "audio") - ], - text: "third page" - ) - ] - ) + private static let books = [ + BookDTO( + id: UUID(), + index: [], + pages: [ + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "image") + ], + text: "first page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "video") + ], + text: "second page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "audio") + ], + text: "third page" + ) + ] + ), + BookDTO( + id: UUID(), + index: [], + pages: [ + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "image") + ], + text: "first page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "video") + ], + text: "second page" + ), + PageDTO( + id: UUID(), + metadata: [ + 0: MediaDescriptionDTO(id: UUID(), type: "audio") + ], + text: "third page" + ) + ] + ) + ] init() async { - _ = await sut.create(data: CoreDataBookStorageTests.book) + _ = await sut.create(data: CoreDataBookStorageTests.books[0]) + _ = await sut.create(data: CoreDataBookStorageTests.books[1]) } @Test func test코어데이터에_새로운_Book_객체를_생성한다() async throws { @@ -85,12 +115,12 @@ struct CoreDataBookStorageTests { @Test func test코어데이터에_저장된_Book_객체를_불러온다() async { // Arrange // Act - let result = await sut.fetch(with: CoreDataBookStorageTests.book.id) + let result = await sut.fetch(with: CoreDataBookStorageTests.books[0].id) // Assert switch result { case .success(let bookResult): - #expect(CoreDataBookStorageTests.book.id == bookResult.id) + #expect(CoreDataBookStorageTests.books.contains(where: { $0.id == bookResult.id })) case .failure(let error): #expect(false, "Fetch Book 실패: \(error.localizedDescription)") } @@ -98,7 +128,7 @@ struct CoreDataBookStorageTests { @Test func test코어데이터에서_특정_UUID값을_가진_Book_데이터를_업데이트한다() async throws { // Arrange - let oldBook = CoreDataBookStorageTests.book + let oldBook = CoreDataBookStorageTests.books[0] let newBook = BookDTO( id: oldBook.id, index: [], @@ -145,25 +175,25 @@ struct CoreDataBookStorageTests { let newBookResult = coreDataBook #expect(newBookResult.pages.count != oldBook.pages.count) case .failure(let error): - #expect(false, "Update BookCover 실패: \(error.localizedDescription)") + #expect(false, "Update Book 실패: \(error.localizedDescription)") } } - @Test(arguments: [CoreDataBookCoverStorageTests.bookCovers[0].identifier, - CoreDataBookCoverStorageTests.bookCovers[1].identifier, + @Test(arguments: [CoreDataBookStorageTests.books[0].id, + CoreDataBookStorageTests.books[1].id, UUID()] ) func test코어데이터에서_특정_UUID값을_가진_BookCover_데이터를_삭제한다(_ id: UUID) async throws { // Arrange // Act let result = await sut.delete(with: id) - let coreDataBookCovers = try await sut.fetch().get() + let coreDataBook = try await sut.fetch(with: id).get() // Assert switch result { case .success: - #expect(!coreDataBookCovers.contains(where: { $0.identifier == id })) + #expect(false, "Delete Book 실패: 삭제된 Book을 찾았습니다.") case .failure(let error): - #expect(error == MHError.findEntityFailure && !coreDataBookCovers.contains(where: { $0.identifier == id })) + #expect(error == MHError.findEntityFailure) } } } From 1204d3655891ed38ae3bb8a912ae48d94eee1f21 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 16:57:51 +0900 Subject: [PATCH 17/44] =?UTF-8?q?chore:=20=EB=A6=B0=ED=8A=B8=20=EA=B2=BD?= =?UTF-8?q?=EA=B3=A0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift index cbe165ce..1539aa48 100644 --- a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift @@ -1,7 +1,6 @@ import MHFoundation import MHDomain - public struct MediaDescriptionDTO { let id: UUID let type: String From 41fa8dcc7c2f7eccab43c190f338a079201b5e12 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 23:30:32 +0900 Subject: [PATCH 18/44] =?UTF-8?q?reafactor:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHCore/MHCore/MHError.swift | 23 +++++++------ MemorialHouse/MHData/MHData/DTO/BookDTO.swift | 2 -- .../CoreData/CoreDataBookCoverStorage.swift | 2 +- .../CoreData/CoreDataBookStorage.swift | 32 ++++++++----------- .../FileManager/MHFileManager.swift | 18 +++++------ .../Repository/LocalBookRepository.swift | 7 ++-- .../MHDomain/MHDomain/Entity/Book.swift | 3 -- .../MHDomain/Repository/BookRepository.swift | 6 ++-- 8 files changed, 42 insertions(+), 51 deletions(-) diff --git a/MemorialHouse/MHCore/MHCore/MHError.swift b/MemorialHouse/MHCore/MHCore/MHError.swift index e8f45254..02e94b1d 100644 --- a/MemorialHouse/MHCore/MHCore/MHError.swift +++ b/MemorialHouse/MHCore/MHCore/MHError.swift @@ -3,13 +3,14 @@ import Foundation public enum MHError: Error, CustomStringConvertible, Equatable { case DIContainerResolveFailure(key: String) case convertDTOFailure + case fetchFaliure case findEntityFailure case saveContextFailure - case directorySettingError - case fileCreationError - case fileReadingError - case fileDeletionError - case fileMovingError + case directorySettingFailure + case fileCreationFailure + case fileReadingFailure + case fileDeletionFailure + case fileMovingFailure public var description: String { switch self { @@ -17,19 +18,21 @@ public enum MHError: Error, CustomStringConvertible, Equatable { "\(key)에 대한 dependency resolve 실패" case .convertDTOFailure: "Entity에 대한 DTO 변환 실패" + case .fetchFaliure: + "Entity Fetch 실패" case .findEntityFailure: "Entity 찾기 실패" case .saveContextFailure: "Update된 Context 저장 실패" - case .directorySettingError: + case .directorySettingFailure: "디렉토리 설정 실패" - case .fileCreationError: + case .fileCreationFailure: "파일 생성 실패" - case .fileReadingError: + case .fileReadingFailure: "파일 읽기 실패" - case .fileDeletionError: + case .fileDeletionFailure: "파일 삭제 실패" - case .fileMovingError: + case .fileMovingFailure: "파일 이동 실패" } } diff --git a/MemorialHouse/MHData/MHData/DTO/BookDTO.swift b/MemorialHouse/MHData/MHData/DTO/BookDTO.swift index eff02523..bb2ead3b 100644 --- a/MemorialHouse/MHData/MHData/DTO/BookDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/BookDTO.swift @@ -3,13 +3,11 @@ import MHDomain public struct BookDTO { let id: UUID - let index: [Int] let pages: [PageDTO] func toBook() -> Book { return Book( id: self.id, - index: self.index, pages: self.pages.map { $0.toPage() } ) } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift index 1c5b33cf..b65b017d 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift @@ -39,7 +39,7 @@ extension CoreDataBookCoverStorage: BookCoverStorage { return .success(result) } catch { MHLogger.debug("Error fetching book covers: \(error.localizedDescription)") - return .failure(.convertDTOFailure) + return .failure(.fetchFaliure) } } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index b7cdf7f9..11fc7341 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -11,7 +11,7 @@ final class CoreDataBookStorage { } extension CoreDataBookStorage: BookStorage { - func create(data: BookDTO) async -> Result { + func create(data: BookDTO) async -> Result { let context = coreDataStorage.persistentContainer.viewContext guard let entity = NSEntityDescription.entity(forEntityName: "BookEntity", in: context) else { return .failure(.DIContainerResolveFailure(key: "BookEntity")) @@ -19,40 +19,32 @@ extension CoreDataBookStorage: BookStorage { let book = NSManagedObject(entity: entity, insertInto: context) book.setValue(data.id, forKey: "id") - book.setValue(data.index, forKey: "index") book.setValue(data.pages, forKey: "pages") await coreDataStorage.saveContext() return .success(()) } - func fetch(with id: UUID) async -> Result { + func fetch(with id: UUID) async -> Result { let context = coreDataStorage.persistentContainer.viewContext - let request = BookEntity.fetchRequest() - - request.predicate = NSPredicate( - format: "id LIKE %@", "\(id.uuidString)" - ) - do { - let bookEntity = try context.fetch(request) - guard let result = bookEntity.first?.toBookDTO() + let bookEntity = try getEntityByIdentifier(in: context, with: id) + guard let result = bookEntity?.toBookDTO() else { throw MHError.convertDTOFailure } return .success(result) } catch { - MHLogger.debug("Error fetching book covers: \(error.localizedDescription)") - return .failure(.convertDTOFailure) + MHLogger.debug("Error fetching book: \(error.localizedDescription)") + return .failure(.fetchFaliure) } } - func update(with id: UUID, data: BookDTO) async -> Result { + func update(with id: UUID, data: BookDTO) async -> Result { do { let context = coreDataStorage.persistentContainer.viewContext guard let newEntity = try getEntityByIdentifier(in: context, with: id) else { return .failure(.findEntityFailure) } newEntity.setValue(data.id, forKey: "id") - newEntity.setValue(data.index, forKey: "index") newEntity.setValue(data.pages, forKey: "pages") await coreDataStorage.saveContext() @@ -61,7 +53,7 @@ extension CoreDataBookStorage: BookStorage { return .failure(.findEntityFailure) } } - func delete(with id: UUID) async -> Result { + func delete(with id: UUID) async -> Result { do { let context = coreDataStorage.persistentContainer.viewContext guard let entity = try getEntityByIdentifier(in: context, with: id) else { @@ -80,19 +72,21 @@ extension CoreDataBookStorage: BookStorage { private func getEntityByIdentifier(in context: NSManagedObjectContext, with id: UUID) throws -> BookEntity? { let request = BookEntity.fetchRequest() - return try context.fetch(request).first(where: { $0.id == id }) + request.predicate = NSPredicate( + format: "id == %@", id as CVarArg + ) + + return try context.fetch(request).first } } extension BookEntity { func toBookDTO() -> BookDTO? { guard let id = self.id, - let index = self.index, let pages = self.pages else { return nil } return BookDTO( id: id, - index: index, pages: pages ) } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift index fbdd116d..4928aa7c 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift @@ -13,7 +13,7 @@ extension MHFileManager: FileStorage { for: directoryType, in: .userDomainMask ).first?.appending(path: path) - else { return .failure(.directorySettingError) } + else { return .failure(.directorySettingFailure) } let dataPath = directory.appendingPathComponent(name) @@ -22,7 +22,7 @@ extension MHFileManager: FileStorage { try data.write(to: dataPath) return .success(()) } catch { - return .failure(.fileCreationError) + return .failure(.fileCreationFailure) } } func read(at path: String, fileName name: String) async -> Result { @@ -30,14 +30,14 @@ extension MHFileManager: FileStorage { for: directoryType, in: .userDomainMask ).first?.appending(path: path) - else { return .failure(.directorySettingError) } + else { return .failure(.directorySettingFailure) } let dataPath = directory.appendingPathComponent(name) do { return .success(try Data(contentsOf: dataPath)) } catch { - return .failure(.fileReadingError) + return .failure(.fileReadingFailure) } } func delete(at path: String, fileName name: String) async -> Result { @@ -45,7 +45,7 @@ extension MHFileManager: FileStorage { for: directoryType, in: .userDomainMask ).first?.appending(path: path) - else { return .failure(.directorySettingError) } + else { return .failure(.directorySettingFailure) } let dataPath = directory.appendingPathComponent(name) @@ -53,7 +53,7 @@ extension MHFileManager: FileStorage { try fileManager.removeItem(at: dataPath) return .success(()) } catch { - return .failure(.fileDeletionError) + return .failure(.fileDeletionFailure) } } func move(at path: String, fileName name: String, to newPath: String) async -> Result { @@ -61,7 +61,7 @@ extension MHFileManager: FileStorage { for: directoryType, in: .userDomainMask ).first?.appending(path: path) - else { return .failure(.directorySettingError) } + else { return .failure(.directorySettingFailure) } let originDataPath = originDirectory.appendingPathComponent(name) @@ -69,7 +69,7 @@ extension MHFileManager: FileStorage { for: directoryType, in: .userDomainMask ).first?.appending(path: newPath) - else { return .failure(.directorySettingError) } + else { return .failure(.directorySettingFailure) } let newDataPath = newDirectory.appendingPathComponent(name) @@ -77,7 +77,7 @@ extension MHFileManager: FileStorage { try fileManager.moveItem(at: originDataPath, to: newDataPath) return .success(()) } catch { - return .failure(.fileMovingError) + return .failure(.fileMovingFailure) } } } diff --git a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift index 355aaee3..40253586 100644 --- a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift +++ b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift @@ -14,7 +14,7 @@ public struct LocalBookRepository: BookRepository { _ = await storage.create(data: bookDTO) } - public func fetchBook(with id: UUID) async -> Book? { + public func fetch(bookID id: UUID) async -> Book? { let result = await storage.fetch(with: id) switch result { @@ -26,12 +26,12 @@ public struct LocalBookRepository: BookRepository { return nil } - public func update(id: UUID, book: Book) async { + public func update(bookID id: UUID, to book: Book) async { let bookDTO = mappingBookToDTO(book) _ = await storage.update(with: id, data: bookDTO) } - public func deleteBook(_ id: UUID) async { + public func delete(bookID id: UUID) async { _ = await storage.delete(with: id) } @@ -39,7 +39,6 @@ public struct LocalBookRepository: BookRepository { let pages = book.pages.map { mappingPageToDTO($0) } return BookDTO( id: book.id, - index: book.index, pages: pages ) } diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift b/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift index 65526068..bb198335 100644 --- a/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift +++ b/MemorialHouse/MHDomain/MHDomain/Entity/Book.swift @@ -2,16 +2,13 @@ import Foundation public struct Book: Identifiable, Sendable { public let id: UUID - public let index: [Int] public let pages: [Page] public init( id: UUID = .init(), - index: [Int], pages: [Page] ) { self.id = id - self.index = index self.pages = pages } } diff --git a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift index 6b999011..0c011bd5 100644 --- a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift +++ b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift @@ -2,7 +2,7 @@ import MHFoundation public protocol BookRepository { func create(book: Book) async - func fetchBook(with id: UUID) async -> Book? - func update(id: UUID, book: Book) async - func deleteBook(_ id: UUID) async + func fetch(bookID id: UUID) async -> Book? + func update(bookID id: UUID, to book: Book) async + func delete(bookID id: UUID) async } From 73e45c7a8b467198c50ad546a23add87cea65868 Mon Sep 17 00:00:00 2001 From: iceHood Date: Tue, 26 Nov 2024 23:30:53 +0900 Subject: [PATCH 19/44] =?UTF-8?q?refactor:=20Test=EA=B0=80=20=EB=8F=99?= =?UTF-8?q?=EC=9E=91=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreDataBookStorageTests.swift | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift index 05262638..d338d658 100644 --- a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift +++ b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift @@ -10,7 +10,6 @@ struct CoreDataBookStorageTests { private static let books = [ BookDTO( id: UUID(), - index: [], pages: [ PageDTO( id: UUID(), @@ -37,7 +36,6 @@ struct CoreDataBookStorageTests { ), BookDTO( id: UUID(), - index: [], pages: [ PageDTO( id: UUID(), @@ -73,7 +71,6 @@ struct CoreDataBookStorageTests { // Arrange let newBook = BookDTO( id: UUID(), - index: [], pages: [ PageDTO( id: UUID(), @@ -131,7 +128,6 @@ struct CoreDataBookStorageTests { let oldBook = CoreDataBookStorageTests.books[0] let newBook = BookDTO( id: oldBook.id, - index: [], pages: [ PageDTO( id: oldBook.pages[0].id, @@ -182,18 +178,25 @@ struct CoreDataBookStorageTests { @Test(arguments: [CoreDataBookStorageTests.books[0].id, CoreDataBookStorageTests.books[1].id, UUID()] - ) func test코어데이터에서_특정_UUID값을_가진_BookCover_데이터를_삭제한다(_ id: UUID) async throws { + ) func test코어데이터에서_특정_UUID값을_가진_BookCover_데이터를_삭제한다(_ id: UUID) async { // Arrange // Act let result = await sut.delete(with: id) - let coreDataBook = try await sut.fetch(with: id).get() + let coreDataBook = await sut.fetch(with: id) // Assert switch result { - case .success: - #expect(false, "Delete Book 실패: 삭제된 Book을 찾았습니다.") - case .failure(let error): + case .success: // 삭제가 되면 성공한 거임 + #expect(true) + case .failure(let error): // 삭제가 실패했을 때 오류를 발생해야 함 #expect(error == MHError.findEntityFailure) } + + switch coreDataBook { + case .success: // 조회가 되면 실패한 거임 + #expect(false, "Delete Book 실패: \(MHError.fetchFaliure.localizedDescription)") + case .failure(let error): // 조회가 실패하면 성공한 거임 + #expect(error == MHError.fetchFaliure) + } } } From 5c7b869abf796d9d53a4490037732c3866a8ada4 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 01:27:55 +0900 Subject: [PATCH 20/44] =?UTF-8?q?refactor:=20=EA=B2=B0=EA=B5=AD=20?= =?UTF-8?q?=EA=B0=96=EC=9D=80=20=EC=98=A4=EB=A5=98=EB=81=9D=EC=97=90=20Dat?= =?UTF-8?q?a=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/DTO/MediaDescriptionDTO.swift | 2 +- MemorialHouse/MHData/MHData/DTO/PageDTO.swift | 2 +- .../CoreData/CoreDataBookStorage.swift | 31 +++++++++++++------ .../MemorialHouseModel.xcdatamodel/contents | 5 ++- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift index 1539aa48..d03ee856 100644 --- a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift @@ -1,7 +1,7 @@ import MHFoundation import MHDomain -public struct MediaDescriptionDTO { +public struct MediaDescriptionDTO: Codable { let id: UUID let type: String diff --git a/MemorialHouse/MHData/MHData/DTO/PageDTO.swift b/MemorialHouse/MHData/MHData/DTO/PageDTO.swift index c60be3a8..3d4fca48 100644 --- a/MemorialHouse/MHData/MHData/DTO/PageDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/PageDTO.swift @@ -1,7 +1,7 @@ import MHFoundation import MHDomain -public struct PageDTO { +public struct PageDTO: Codable { let id: UUID let metadata: [Int: MediaDescriptionDTO] let text: String diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index 11fc7341..6012aa9d 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -19,7 +19,7 @@ extension CoreDataBookStorage: BookStorage { let book = NSManagedObject(entity: entity, insertInto: context) book.setValue(data.id, forKey: "id") - book.setValue(data.pages, forKey: "pages") + book.setValue(DTOPagesToCore(data.pages), forKey: "pages") await coreDataStorage.saveContext() return .success(()) @@ -28,14 +28,16 @@ extension CoreDataBookStorage: BookStorage { let context = coreDataStorage.persistentContainer.viewContext do { - let bookEntity = try getEntityByIdentifier(in: context, with: id) - guard let result = bookEntity?.toBookDTO() - else { throw MHError.convertDTOFailure } + guard let bookEntity = try getEntityByIdentifier(in: context, with: id) + else { return .failure(.findEntityFailure) } + + guard let result = coreBookToDTO(bookEntity) + else { return .failure(.convertDTOFailure) } return .success(result) } catch { MHLogger.debug("Error fetching book: \(error.localizedDescription)") - return .failure(.fetchFaliure) + return .failure(.findEntityFailure) } } func update(with id: UUID, data: BookDTO) async -> Result { @@ -45,7 +47,7 @@ extension CoreDataBookStorage: BookStorage { return .failure(.findEntityFailure) } newEntity.setValue(data.id, forKey: "id") - newEntity.setValue(data.pages, forKey: "pages") + newEntity.setValue(DTOPagesToCore(data.pages), forKey: "pages") await coreDataStorage.saveContext() return .success(()) @@ -80,14 +82,23 @@ extension CoreDataBookStorage: BookStorage { } } -extension BookEntity { - func toBookDTO() -> BookDTO? { - guard let id = self.id, - let pages = self.pages else { return nil } +// MARK: - Mapper +extension CoreDataBookStorage { + // MARK: - Core to DTO + private func coreBookToDTO(_ book: BookEntity) -> BookDTO? { + guard let id = book.id, + let pages = try? JSONDecoder().decode([PageDTO].self, from: book.pages ?? Data()) + else { return nil } return BookDTO( id: id, pages: pages ) } + + // MARK: - DTO to Core + private func DTOPagesToCore(_ pages: [PageDTO]) -> Data? { + guard let data = try? JSONEncoder().encode(pages) else { return nil } + return data + } } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents index ea5c063b..d0ec16d3 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -10,7 +10,6 @@ - - + \ No newline at end of file From 4f6bc8c22c3d5e82f4664680a81409c8a070905b Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 01:28:34 +0900 Subject: [PATCH 21/44] =?UTF-8?q?feat:=20FIleManager=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FileManager/MHFileManager.swift | 7 +- .../CoreDataBookStorageTests.swift | 2 +- .../MHDataTests/MHFileManagerTests.swift | 131 ++++++++++++++++++ 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift index 4928aa7c..a3766821 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift @@ -5,6 +5,10 @@ import MHDomain public struct MHFileManager { private let fileManager = FileManager.default private let directoryType: FileManager.SearchPathDirectory + + public init(directoryType: FileManager.SearchPathDirectory) { + self.directoryType = directoryType + } } extension MHFileManager: FileStorage { @@ -18,7 +22,7 @@ extension MHFileManager: FileStorage { let dataPath = directory.appendingPathComponent(name) do { - try fileManager.createDirectory(at: directory, withIntermediateDirectories: false) + try fileManager.createDirectory(at: directory, withIntermediateDirectories: true) try data.write(to: dataPath) return .success(()) } catch { @@ -74,6 +78,7 @@ extension MHFileManager: FileStorage { let newDataPath = newDirectory.appendingPathComponent(name) do { + try fileManager.createDirectory(at: newDirectory, withIntermediateDirectories: true) try fileManager.moveItem(at: originDataPath, to: newDataPath) return .success(()) } catch { diff --git a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift index d338d658..404447b0 100644 --- a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift +++ b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift @@ -196,7 +196,7 @@ struct CoreDataBookStorageTests { case .success: // 조회가 되면 실패한 거임 #expect(false, "Delete Book 실패: \(MHError.fetchFaliure.localizedDescription)") case .failure(let error): // 조회가 실패하면 성공한 거임 - #expect(error == MHError.fetchFaliure) + #expect(error == MHError.findEntityFailure) } } } diff --git a/MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift b/MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift new file mode 100644 index 00000000..7daed505 --- /dev/null +++ b/MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift @@ -0,0 +1,131 @@ +import Testing +@testable import MHData +@testable import MHFoundation + +@Suite("Serial model tests", .serialized) final class MHFileManagerTests { + private var fileManager: MHFileManager! + private let testDirectory = "TestDirectory" + private let newTestDirectory = "NewTestDirectory" + private let testFileName = "testFile.txt" + private let testFileData = "Hello, File!".data(using: .utf8)! + + init() { + self.fileManager = MHFileManager(directoryType: .documentDirectory) + } + + @Test func test파일생성_성공() async { + // Arrange + let path = testDirectory + + // Act + let result = await fileManager.create(at: path, fileName: testFileName, data: testFileData) + + // Assert + switch result { + case .success: + let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + let fileURL = directoryURL.appendingPathComponent(path).appendingPathComponent(testFileName) + #expect(FileManager.default.fileExists(atPath: fileURL.path)) + case .failure(let error): + #expect(false, "\(#function) 실패함: \(error)") + } + } + @Test func test파일읽기_성공() async { + // Arrange + let path = testDirectory + _ = await fileManager.create(at: path, fileName: testFileName, data: testFileData) + + // Act + let result = await fileManager.read(at: path, fileName: testFileName) + + // Assert + switch result { + case .success(let data): + #expect(data == testFileData) + case .failure(let error): + #expect(false, "\(#function) 실패함: \(error)") + } + } + @Test func test없는_파일읽기_실패() async { + // Arrange + let path = testDirectory + + // Act + let result = await fileManager.read(at: path, fileName: "nonExistentFile.txt") + + // Assert + switch result { + case .success: + #expect(false, "\(#function) 실패해야하는데 성공함") + case .failure(let error): + #expect(error == .fileReadingFailure) + } + } + @Test func test파일삭제_성공() async { + // Arrange + let path = testDirectory + _ = await fileManager.create(at: path, fileName: testFileName, data: testFileData) + + // Act + let result = await fileManager.delete(at: path, fileName: testFileName) + + // Assert + switch result { + case .success: + let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + let fileURL = directoryURL.appendingPathComponent(path).appendingPathComponent(testFileName) + #expect(!FileManager.default.fileExists(atPath: fileURL.path)) + case .failure(let error): + #expect(false, "\(#function) 실패함: \(error)") + } + } + @Test func test없는_파일삭제_실패() async { + // Arrange + let path = testDirectory + + // Act + let result = await fileManager.delete(at: path, fileName: testFileName) + + // Assert + switch result { + case .success: + #expect(false, "\(#function) 실패해야하는데 성공함") + case .failure(let error): + #expect(error == .fileDeletionFailure) + } + } + @Test func test파일이동_성공() async { + // Arrange + let path = testDirectory + _ = await fileManager.create(at: path, fileName: testFileName, data: testFileData) + + // Act + let newPath = newTestDirectory + let result = await fileManager.move(at: path, fileName: testFileName, to: newPath) + + // Assert + switch result { + case .success: + let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + let newFileURL = directoryURL.appendingPathComponent(newPath).appendingPathComponent(testFileName) + #expect(FileManager.default.fileExists(atPath: newFileURL.path)) + case .failure(let error): + #expect(false, "\(#function) 실패함: \(error)") + } + } + + + deinit { + // 테스트 디렉토리와 관련된 파일 정리 + let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + let testDirectoryURL = directoryURL.appendingPathComponent(testDirectory) + let newTestDirectoryURL = directoryURL.appendingPathComponent(newTestDirectory) + + if FileManager.default.fileExists(atPath: testDirectoryURL.path) { + try? FileManager.default.removeItem(at: testDirectoryURL) + } + if FileManager.default.fileExists(atPath: newTestDirectoryURL.path) { + try? FileManager.default.removeItem(at: newTestDirectoryURL) + } + } +} From d4a6e597201e325baa76819f44548b44b36986e7 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 01:28:55 +0900 Subject: [PATCH 22/44] =?UTF-8?q?feat:=20MediaRepository=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=86=A0=EC=BD=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHDomain/MHDomain/Repository/MediaRepository.swift | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift diff --git a/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift b/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift new file mode 100644 index 00000000..87efec72 --- /dev/null +++ b/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift @@ -0,0 +1,8 @@ +import MHFoundation + +public protocol MediaRepository { + func create(at path: String, fileName name: String, data: Data) async + func read(at path: String, fileName name: String) async -> Data? + func delete(at path: String, fileName name: String) async + func move(at path: String, fileName name: String, to newPath: String) async +} From 0109995beda9eba67609c349ce1aa1e2e536fae8 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 09:26:26 +0900 Subject: [PATCH 23/44] =?UTF-8?q?feat:=20dto=20=EB=A7=A4=ED=8D=BC=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/LocalStorage/CoreData/CoreDataBookStorage.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index 6012aa9d..04e4898c 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -19,7 +19,7 @@ extension CoreDataBookStorage: BookStorage { let book = NSManagedObject(entity: entity, insertInto: context) book.setValue(data.id, forKey: "id") - book.setValue(DTOPagesToCore(data.pages), forKey: "pages") + book.setValue(dtoPagesToCore(data.pages), forKey: "pages") await coreDataStorage.saveContext() return .success(()) @@ -47,7 +47,7 @@ extension CoreDataBookStorage: BookStorage { return .failure(.findEntityFailure) } newEntity.setValue(data.id, forKey: "id") - newEntity.setValue(DTOPagesToCore(data.pages), forKey: "pages") + newEntity.setValue(dtoPagesToCore(data.pages), forKey: "pages") await coreDataStorage.saveContext() return .success(()) @@ -97,7 +97,7 @@ extension CoreDataBookStorage { } // MARK: - DTO to Core - private func DTOPagesToCore(_ pages: [PageDTO]) -> Data? { + private func dtoPagesToCore(_ pages: [PageDTO]) -> Data? { guard let data = try? JSONEncoder().encode(pages) else { return nil } return data } From 10f59e41310c55c7b93a92edf23ec19a2fed61f1 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 15:55:39 +0900 Subject: [PATCH 24/44] =?UTF-8?q?refactor:=20FileStroage=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=95=A8=EC=88=98=20=EB=B0=8F=20=EC=84=A4=EB=AA=85?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/LocalStorage/FileStorage.swift | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift index 44f937c7..a01987dd 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift @@ -1,9 +1,73 @@ import MHFoundation import MHCore -protocol FileStorage { +public protocol FileStorage { + + /// 지정된 경로에 파일을 생성합니다. + /// Documents폴더에 파일을 생성합니다. + /// 중간 경로 폴더를 자동으로 생성합니다. + /// - Parameters: + /// - path: Documents/{path} 이런식으로 들어갑니다. + /// - name: Documents/{path}/{name} 이런식으로 저장됩니다. (확장자 명시 필요) + /// - data: 실제 저장될 데이터 + /// - Returns: 성공여부를 반환합니다. func create(at path: String, fileName name: String, data: Data) async -> Result + + /// 지정된 경로의 파일을 읽어옵니다. + /// Documents폴더에서 파일을 읽어옵니다 + /// - Parameters: + /// - path: Documents/{path} 이런식으로 들어갑니다. + /// - name: Documents/{path}/{name} 이런식으로 읽어옵니다. (확장자 명시 필요) + /// - Returns: 파일 데이터를 반환합니다. func read(at path: String, fileName name: String) async -> Result + + /// 지정된 경로의 파일을 삭제합니다. + /// Documents폴더에서 파일을 삭제합니다. + /// - Parameters: + /// - path: Documents/{path} 이런식으로 들어갑니다. + /// - name: Documents/{path}/{name} 이런식으로 삭제합니다. (확장자 명시 필요) + /// - Returns: 성공여부를 반환합니다. func delete(at path: String, fileName name: String) async -> Result + + /// 지정된 경로의 파일을 새로운 파일 이름으로 복사합니다. + /// 지정된 경로 -> Documents폴더로 파일을 복사합니다. + /// - Parameters: + /// - url: 내부 저장소의 파일 URL (AVURLAsset등의 URL호환) + /// - newPath: Documents/{newPath} 이런식으로 들어갑니다. + /// - name: Documents/{newPath}/{name} 이런식으로 저장됩니다. (확장자 명시 필요) + /// - Returns: 성공여부를 반환합니다. + func copy(at url: URL, to newPath: String, newFileName name: String) async -> Result + + /// 지정된 경로의 파일을 복사합니다. + /// Documents폴더 -> Documents폴더로 파일을 복사합니다. + /// Documents/{path}/{name} => Documents/{newPath}/{name} 이런식으로 복사합니다. + /// - Parameters: + /// - path: Documents/{path} 이런식으로 들어갑니다 + /// - name: Documents/{path}/{name} 이 파일을 복사합니다. (확장자 명시 필요) + /// - newPath: Documents/{newPath}/{name} 으로 저장합니다. + /// - Returns: 성공여부를 반환합니다. + func copy(at path: String, fileName name: String, to newPath: String) async -> Result + + /// 지정된 경로의 파일을 이동합니다. + /// - Parameters: + /// - path: Documents/{path} 이런식으로 들어갑니다 + /// - name: Documents/{path}/{name} 이 파일을 이동합니다. (확장자 명시 필요) + /// - newPath: Documents/{newPath}/{name} 으로 이동합니다. + /// - Returns: 성공여부를 반환합니다. func move(at path: String, fileName name: String, to newPath: String) async -> Result + + /// 지정된 경로의 모든 파일을 이동합니다. + /// - Parameters: + /// - path: Documents/{path} 이런식으로 들어갑니다 + /// - newPath: Documents/{newPath} 으로 이동합니다. + /// - Returns: 성공여부를 반환합니다. + func moveAll(in path: String, to newPath: String) async -> Result + + /// 지정된 경로의 로컬 파일 URL을 반환합니다. + /// Documents폴더기준으로 파일 URL을 반환합니다. + /// - Parameters: + /// - path: Documents/{path} 이런식으로 들어갑니다 + /// - name: Documents/{path}/{name} 이 파일 URL을 반환합니다. (확장자 명시 필요) + /// - Returns: 파일 URL을 반환합니다. + func getURL(at path: String, fileName name: String) async -> Result } From 768f42fb0268abd33b963e81cd8ef7340dfd4434 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 15:55:51 +0900 Subject: [PATCH 25/44] =?UTF-8?q?feat:=20FileManage=20=EC=8B=A0=EA=B7=9C?= =?UTF-8?q?=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FileManager/MHFileManager.swift | 108 +++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift index a3766821..41dda3e3 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift @@ -1,12 +1,12 @@ import MHFoundation import MHCore -import MHDomain +//import MHDomain -public struct MHFileManager { +struct MHFileManager { private let fileManager = FileManager.default private let directoryType: FileManager.SearchPathDirectory - public init(directoryType: FileManager.SearchPathDirectory) { + init(directoryType: FileManager.SearchPathDirectory) { self.directoryType = directoryType } } @@ -38,6 +38,10 @@ extension MHFileManager: FileStorage { let dataPath = directory.appendingPathComponent(name) + guard fileManager.fileExists(atPath: dataPath.path) else { + return .failure(.fileNotExists) + } + do { return .success(try Data(contentsOf: dataPath)) } catch { @@ -60,6 +64,58 @@ extension MHFileManager: FileStorage { return .failure(.fileDeletionFailure) } } + func copy(at url: URL, to newPath: String, newFileName name: String) async -> Result { + let originDataPath = url + + guard fileManager.fileExists(atPath: originDataPath.path) else { + return .failure(.fileNotExists) + } + + guard let newDirectory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: newPath) + else { return .failure(.directorySettingFailure) } + + let newDataPath = newDirectory.appendingPathComponent(name) + + do { + try fileManager.createDirectory(at: newDirectory, withIntermediateDirectories: true) + try fileManager.copyItem(at: originDataPath, to: newDataPath) + return .success(()) + } catch { + return .failure(.fileMovingFailure) + } + } + func copy(at path: String, fileName name: String, to newPath: String) async -> Result { + guard let originDirectory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: path) + else { return .failure(.directorySettingFailure) } + + let originDataPath = originDirectory.appendingPathComponent(name) + + guard fileManager.fileExists(atPath: originDataPath.path) else { + return .failure(.fileNotExists) + } + + guard let newDirectory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: newPath) + else { return .failure(.directorySettingFailure) } + + let newDataPath = newDirectory.appendingPathComponent(name) + + do { + try fileManager.createDirectory(at: newDirectory, withIntermediateDirectories: true) + try fileManager.copyItem(at: originDataPath, to: newDataPath) + return .success(()) + } catch { + return .failure(.fileMovingFailure) + } + } func move(at path: String, fileName name: String, to newPath: String) async -> Result { guard let originDirectory = fileManager.urls( for: directoryType, @@ -69,6 +125,10 @@ extension MHFileManager: FileStorage { let originDataPath = originDirectory.appendingPathComponent(name) + guard fileManager.fileExists(atPath: originDataPath.path) else { + return .failure(.fileNotExists) + } + guard let newDirectory = fileManager.urls( for: directoryType, in: .userDomainMask @@ -85,4 +145,46 @@ extension MHFileManager: FileStorage { return .failure(.fileMovingFailure) } } + func moveAll(in path: String, to newPath: String) async -> Result { + guard let originDirectory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: path) + else { return .failure(.directorySettingFailure) } + + guard fileManager.fileExists(atPath: originDirectory.path) else { + return .failure(.fileNotExists) + } + + guard let newDirectory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: newPath) + else { return .failure(.directorySettingFailure) } + + do { + let files = try fileManager.contentsOfDirectory(atPath: originDirectory.path) + try fileManager.createDirectory(at: newDirectory, withIntermediateDirectories: true) + for file in files { + let originDataPath = originDirectory.appendingPathComponent(file) + let newDataPath = newDirectory.appendingPathComponent(file) + try fileManager.moveItem(at: originDataPath, to: newDataPath) + } + return .success(()) + } catch { + return .failure(.fileMovingFailure) + } + } + func getURL(at path: String, fileName name: String) async -> Result { + guard let originDirectory = fileManager.urls( + for: directoryType, + in: .userDomainMask + ).first?.appending(path: path) + else { return .failure(.directorySettingFailure) } + + let originDataPath = originDirectory.appendingPathComponent(name) + + return .success(originDataPath) + } } + From 56e89d310585a6eabd0fe4d6512d8937ce7f948a Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 15:56:37 +0900 Subject: [PATCH 26/44] =?UTF-8?q?feat:=20LocalMediaRepository=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/LocalMediaRepository.swift | 66 +++++++++++++++++++ .../MHDomain/Repository/MediaRepository.swift | 13 ++-- 2 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift diff --git a/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift new file mode 100644 index 00000000..f775b7b9 --- /dev/null +++ b/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift @@ -0,0 +1,66 @@ +import MHFoundation +import Photos +import MHDomain +import MHCore +import AVFoundation + +public struct LocalMediaRepository: MediaRepository { + + private let storage: FileStorage + + public init(storage: FileStorage) { + self.storage = storage + } + + public func create(media mediaDescription: MediaDescription, data: Data, to bookID: UUID?) async -> Result { + let path = bookID == nil + ? "temp" + : bookID!.uuidString + let fileName = mediaDescription.id.uuidString + + return await storage.create(at: path, fileName: fileName, data: data) + } + public func create(media mediaDescription: MediaDescription, from: URL, to bookID: UUID?) async -> Result { + let path = bookID == nil + ? "temp" + : bookID!.uuidString + let fileName = mediaDescription.id.uuidString + + return await storage.copy(at: from, to: path, newFileName: fileName) + } + public func read(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result { + let path = bookID == nil + ? "temp" + : bookID!.uuidString + let fileName = mediaDescription.id.uuidString + + return await storage.read(at: path, fileName: fileName) + } + public func getURL(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result { + let path = bookID == nil + ? "temp" + : bookID!.uuidString + let fileName = mediaDescription.id.uuidString + + return await storage.getURL(at: path, fileName: fileName) + } + public func delete(media mediaDescription: MediaDescription, at bookID: UUID?) async -> Result { + let path = bookID == nil + ? "temp" + : bookID!.uuidString + let fileName = mediaDescription.id.uuidString + + return await storage.delete(at: path, fileName: fileName) + } + public func moveTemporaryMedia(_ mediaDescription: MediaDescription, to bookID: UUID) async -> Result { + let path = bookID.uuidString + let fileName = mediaDescription.id.uuidString + + return await storage.move(at: "temp", fileName: fileName, to: path) + } + public func moveAllTemporaryMedia(to bookID: UUID) async -> Result { + let path = bookID.uuidString + + return await storage.moveAll(in: "temp", to: path) + } +} diff --git a/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift b/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift index 87efec72..0c36f704 100644 --- a/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift +++ b/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift @@ -1,8 +1,13 @@ import MHFoundation +import MHCore +import Photos public protocol MediaRepository { - func create(at path: String, fileName name: String, data: Data) async - func read(at path: String, fileName name: String) async -> Data? - func delete(at path: String, fileName name: String) async - func move(at path: String, fileName name: String, to newPath: String) async + func create(media mediaDescription: MediaDescription, data: Data, to bookID: UUID?) async -> Result + func create(media mediaDescription: MediaDescription, from: URL, to bookID: UUID?) async -> Result + func read(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result + func getURL(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result + func delete(media mediaDescription: MediaDescription, at bookID: UUID?) async -> Result + func moveTemporaryMedia(_ mediaDescription: MediaDescription, to bookID: UUID) async -> Result + func moveAllTemporaryMedia(to bookID: UUID) async -> Result } From d9f5a6a734cb98263a5c6be0eeefb61679e6b5a0 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 15:56:49 +0900 Subject: [PATCH 27/44] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=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 --- MemorialHouse/MHCore/MHCore/MHError.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MemorialHouse/MHCore/MHCore/MHError.swift b/MemorialHouse/MHCore/MHCore/MHError.swift index 02e94b1d..98abe629 100644 --- a/MemorialHouse/MHCore/MHCore/MHError.swift +++ b/MemorialHouse/MHCore/MHCore/MHError.swift @@ -11,6 +11,7 @@ public enum MHError: Error, CustomStringConvertible, Equatable { case fileReadingFailure case fileDeletionFailure case fileMovingFailure + case fileNotExists public var description: String { switch self { @@ -34,6 +35,8 @@ public enum MHError: Error, CustomStringConvertible, Equatable { "파일 삭제 실패" case .fileMovingFailure: "파일 이동 실패" + case .fileNotExists: + "파일이 존재하지 않습니다" } } } From 0518b74896931692afd1ef7b3bd730c55e3bd8fa Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 15:57:17 +0900 Subject: [PATCH 28/44] =?UTF-8?q?refactor:=20Repository=EC=97=90=EC=84=9C?= =?UTF-8?q?=20result=EB=A1=9C=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/LocalBookRepository.swift | 23 +++++++++---------- .../MHDomain/Repository/BookRepository.swift | 9 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift index 40253586..72ad49c0 100644 --- a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift +++ b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift @@ -9,30 +9,29 @@ public struct LocalBookRepository: BookRepository { self.storage = storage } - public func create(book: Book) async { + public func create(book: Book) async -> Result { let bookDTO = mappingBookToDTO(book) - _ = await storage.create(data: bookDTO) + return await storage.create(data: bookDTO) } - public func fetch(bookID id: UUID) async -> Book? { + public func fetch(bookID id: UUID) async -> Result { let result = await storage.fetch(with: id) switch result { - case .success(let bookDTO): - return bookDTO.toBook() - case .failure(let failure): + case let .success(bookDTO): + return .success(bookDTO.toBook()) + case let .failure(failure): MHLogger.debug("\(failure.description)") + return .failure(failure) } - - return nil } - public func update(bookID id: UUID, to book: Book) async { + public func update(bookID id: UUID, to book: Book) async -> Result { let bookDTO = mappingBookToDTO(book) - _ = await storage.update(with: id, data: bookDTO) + return await storage.update(with: id, data: bookDTO) } - public func delete(bookID id: UUID) async { - _ = await storage.delete(with: id) + public func delete(bookID id: UUID) async -> Result { + return await storage.delete(with: id) } private func mappingBookToDTO(_ book: Book) -> BookDTO { diff --git a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift index 0c011bd5..26a129c9 100644 --- a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift +++ b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift @@ -1,8 +1,9 @@ import MHFoundation +import MHCore public protocol BookRepository { - func create(book: Book) async - func fetch(bookID id: UUID) async -> Book? - func update(bookID id: UUID, to book: Book) async - func delete(bookID id: UUID) async + func create(book: Book) async -> Result + func fetch(bookID id: UUID) async -> Result + func update(bookID id: UUID, to book: Book) async -> Result + func delete(bookID id: UUID) async -> Result } From e251e11c403f6b3c2a6eef7b17f4c40ee576c73e Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 16:01:27 +0900 Subject: [PATCH 29/44] =?UTF-8?q?refactor:=20=EC=83=88=EB=A1=9C=EC=9A=B4?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=EC=97=90=20=EB=8C=80=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift b/MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift index 7daed505..f49f8ef7 100644 --- a/MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift +++ b/MemorialHouse/MHData/MHDataTests/MHFileManagerTests.swift @@ -2,7 +2,7 @@ import Testing @testable import MHData @testable import MHFoundation -@Suite("Serial model tests", .serialized) final class MHFileManagerTests { +@Suite("FileManager 순차적으로 테스트", .serialized) final class MHFileManagerTests { private var fileManager: MHFileManager! private let testDirectory = "TestDirectory" private let newTestDirectory = "NewTestDirectory" @@ -58,7 +58,7 @@ import Testing case .success: #expect(false, "\(#function) 실패해야하는데 성공함") case .failure(let error): - #expect(error == .fileReadingFailure) + #expect(error == .fileNotExists) } } @Test func test파일삭제_성공() async { From 64c488744edb3656415b906dc1a51ffcf60cad48 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 16:49:30 +0900 Subject: [PATCH 30/44] =?UTF-8?q?refactor:=20Decodable=EB=8C=80=EC=8B=A0?= =?UTF-8?q?=20CoreData=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreData/CoreDataBookStorage.swift | 82 ++++++++++++++++++- .../MemorialHouseModel.xcdatamodel/contents | 16 +++- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index 04e4898c..d38ff0c0 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -87,18 +87,92 @@ extension CoreDataBookStorage { // MARK: - Core to DTO private func coreBookToDTO(_ book: BookEntity) -> BookDTO? { guard let id = book.id, - let pages = try? JSONDecoder().decode([PageDTO].self, from: book.pages ?? Data()) + let corePages = book.pages else { return nil } + let pages = corePagesToDTO(corePages) return BookDTO( id: id, pages: pages ) } + private func corePagesToDTO(_ pages: NSOrderedSet) -> [PageDTO] { + return pages.compactMap { + guard let page = $0 as? PageEntity else { return nil } + return corePageToDTO(page) + } + } + private func corePageToDTO(_ page: PageEntity) -> PageDTO? { + guard let id = page.id, + let mediaDescriptions = page.mediaDescriptions, + let text = page.text + else { return nil } + + let metadata = mediaDescriptions.reduce(into: [Int: MediaDescriptionDTO]()) { partialResult, element in + guard let element = element as? MediaDescriptionEntity else { return } + guard let (index, mediaDescription) = coreMediaDescriptionToDTO(element) else { return } + partialResult[index] = mediaDescription + } + + return PageDTO( + id: id, + metadata: metadata, + text: text + ) + } + private func coreMediaDescriptionToDTO(_ mediaDescription: MediaDescriptionEntity) -> (Int, MediaDescriptionDTO)? { + guard let id = mediaDescription.id, + let type = mediaDescription.type + else { return nil } + let location = mediaDescription.location + return (Int(location), MediaDescriptionDTO( + id: id, + type: type + )) + } // MARK: - DTO to Core - private func dtoPagesToCore(_ pages: [PageDTO]) -> Data? { - guard let data = try? JSONEncoder().encode(pages) else { return nil } - return data + private func dtoPagesToCore(_ pages: [PageDTO]) -> NSOrderedSet? { + let context = coreDataStorage.persistentContainer.viewContext + let pageEntities = pages.compactMap { dtoPageToCore($0, in: context) } + return NSOrderedSet(array: pageEntities) } + + private func dtoPageToCore(_ page: PageDTO, in context: NSManagedObjectContext) -> PageEntity? { + guard let entity = NSEntityDescription.insertNewObject(forEntityName: "PageEntity", into: context) as? PageEntity else { + return nil + } + + entity.id = page.id + entity.text = page.text + entity.mediaDescriptions = dtoMediaDescriptionsToCore(page.metadata, in: context) + + return entity + } + + private func dtoMediaDescriptionsToCore( + _ metadata: [Int: MediaDescriptionDTO], + in context: NSManagedObjectContext + ) -> NSSet? { + let mediaDescriptionEntities = metadata.compactMap { location, description in + dtoMediaDescriptionToCore(location: location, description, in: context) + } + return NSSet(array: mediaDescriptionEntities) + } + private func dtoMediaDescriptionToCore( + location: Int, + _ mediaDescription: MediaDescriptionDTO, + in context: NSManagedObjectContext + ) -> MediaDescriptionEntity? { + guard let entity = NSEntityDescription.insertNewObject(forEntityName: "MediaDescriptionEntity", into: context) as? MediaDescriptionEntity else { + return nil + } + + entity.id = mediaDescription.id + entity.type = mediaDescription.type + entity.location = Int64(location) + + return entity + } + } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents index d0ec16d3..18959f6f 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -10,6 +10,18 @@ - + + + + + + + + + + + + + \ No newline at end of file From c7a74bd42b9c2e0f8bdfe49827b6cf52ab540735 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 16:57:53 +0900 Subject: [PATCH 31/44] =?UTF-8?q?chore:=20Lint=EA=B2=BD=EA=B3=A0=20?= =?UTF-8?q?=EC=95=88=EB=82=98=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LocalStorage/CoreData/CoreDataBookStorage.swift | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index d38ff0c0..831db538 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -137,9 +137,11 @@ extension CoreDataBookStorage { let pageEntities = pages.compactMap { dtoPageToCore($0, in: context) } return NSOrderedSet(array: pageEntities) } - private func dtoPageToCore(_ page: PageDTO, in context: NSManagedObjectContext) -> PageEntity? { - guard let entity = NSEntityDescription.insertNewObject(forEntityName: "PageEntity", into: context) as? PageEntity else { + guard let entity = NSEntityDescription.insertNewObject( + forEntityName: "PageEntity", + into: context + ) as? PageEntity else { return nil } @@ -149,7 +151,6 @@ extension CoreDataBookStorage { return entity } - private func dtoMediaDescriptionsToCore( _ metadata: [Int: MediaDescriptionDTO], in context: NSManagedObjectContext @@ -164,7 +165,10 @@ extension CoreDataBookStorage { _ mediaDescription: MediaDescriptionDTO, in context: NSManagedObjectContext ) -> MediaDescriptionEntity? { - guard let entity = NSEntityDescription.insertNewObject(forEntityName: "MediaDescriptionEntity", into: context) as? MediaDescriptionEntity else { + guard let entity = NSEntityDescription.insertNewObject( + forEntityName: "MediaDescriptionEntity", + into: context + ) as? MediaDescriptionEntity else { return nil } @@ -174,5 +178,4 @@ extension CoreDataBookStorage { return entity } - } From 7e6a62eb99e50d4205fa081cf4909c092adc26e3 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 20:19:24 +0900 Subject: [PATCH 32/44] =?UTF-8?q?refactor:=20DTO=EC=97=90=20public=20init?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHData/MHData/DTO/BookCoverDTO.swift | 9 +++++++++ MemorialHouse/MHData/MHData/DTO/BookDTO.swift | 5 +++++ .../MHData/MHData/DTO/MediaDescriptionDTO.swift | 7 ++++++- MemorialHouse/MHData/MHData/DTO/PageDTO.swift | 8 +++++++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/MemorialHouse/MHData/MHData/DTO/BookCoverDTO.swift b/MemorialHouse/MHData/MHData/DTO/BookCoverDTO.swift index 0f0b68fc..667cbc96 100644 --- a/MemorialHouse/MHData/MHData/DTO/BookCoverDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/BookCoverDTO.swift @@ -9,6 +9,15 @@ public struct BookCoverDTO { let category: String? let favorite: Bool + public init(identifier: UUID, title: String, imageURL: String?, color: String, category: String?, favorite: Bool) { + self.identifier = identifier + self.title = title + self.imageURL = imageURL + self.color = color + self.category = category + self.favorite = favorite + } + func toBookCover() -> BookCover? { guard let color = BookColor(rawValue: self.color) else { return nil } diff --git a/MemorialHouse/MHData/MHData/DTO/BookDTO.swift b/MemorialHouse/MHData/MHData/DTO/BookDTO.swift index bb2ead3b..27c1edce 100644 --- a/MemorialHouse/MHData/MHData/DTO/BookDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/BookDTO.swift @@ -5,6 +5,11 @@ public struct BookDTO { let id: UUID let pages: [PageDTO] + public init(id: UUID, pages: [PageDTO]) { + self.id = id + self.pages = pages + } + func toBook() -> Book { return Book( id: self.id, diff --git a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift index d03ee856..9c623a45 100644 --- a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift @@ -1,10 +1,15 @@ import MHFoundation import MHDomain -public struct MediaDescriptionDTO: Codable { +public struct MediaDescriptionDTO { let id: UUID let type: String + public init(id: UUID, type: String) { + self.id = id + self.type = type + } + func toMediaDescription() -> MediaDescription? { guard let type = MediaType(rawValue: self.type) else { return nil } diff --git a/MemorialHouse/MHData/MHData/DTO/PageDTO.swift b/MemorialHouse/MHData/MHData/DTO/PageDTO.swift index 3d4fca48..c73cf2e1 100644 --- a/MemorialHouse/MHData/MHData/DTO/PageDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/PageDTO.swift @@ -1,11 +1,17 @@ import MHFoundation import MHDomain -public struct PageDTO: Codable { +public struct PageDTO { let id: UUID let metadata: [Int: MediaDescriptionDTO] let text: String + public init(id: UUID, metadata: [Int : MediaDescriptionDTO], text: String) { + self.id = id + self.metadata = metadata + self.text = text + } + func toPage() -> Page { let metadata = self.metadata .compactMapValues { $0.toMediaDescription() } From 551dd1869e39f86f83e93f538dc1821a8a9d1012 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 20:40:49 +0900 Subject: [PATCH 33/44] refactor: MHError -> MHCoreError / MHDataError --- .../xcschemes/MemorialHouse.xcscheme | 78 +++++++++++++++++++ .../Source/App/SceneDelegate.swift | 2 +- MemorialHouse/MHCore/MHCore/DIContainer.swift | 2 +- MemorialHouse/MHCore/MHCore/MHCoreError.swift | 12 +++ .../{MHError.swift => MHDataError.swift} | 7 +- .../LocalStorage/BookCoverStorage.swift | 8 +- .../MHData/LocalStorage/BookStorage.swift | 8 +- .../CoreData/CoreDataBookCoverStorage.swift | 8 +- .../CoreData/CoreDataBookStorage.swift | 8 +- .../FileManager/MHFileManager.swift | 17 ++-- .../MHData/LocalStorage/FileStorage.swift | 16 ++-- .../Repository/LocalBookRepository.swift | 8 +- .../Repository/LocalMediaRepository.swift | 14 ++-- .../MHDomain/Repository/BookRepository.swift | 8 +- .../MHDomain/Repository/MediaRepository.swift | 14 ++-- 15 files changed, 148 insertions(+), 62 deletions(-) create mode 100644 MemorialHouse/MHApplication/MHApplication.xcodeproj/xcshareddata/xcschemes/MemorialHouse.xcscheme create mode 100644 MemorialHouse/MHCore/MHCore/MHCoreError.swift rename MemorialHouse/MHCore/MHCore/{MHError.swift => MHDataError.swift} (81%) diff --git a/MemorialHouse/MHApplication/MHApplication.xcodeproj/xcshareddata/xcschemes/MemorialHouse.xcscheme b/MemorialHouse/MHApplication/MHApplication.xcodeproj/xcshareddata/xcschemes/MemorialHouse.xcscheme new file mode 100644 index 00000000..684613f1 --- /dev/null +++ b/MemorialHouse/MHApplication/MHApplication.xcodeproj/xcshareddata/xcschemes/MemorialHouse.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift b/MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift index 1238b440..33980944 100644 --- a/MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift +++ b/MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift @@ -51,7 +51,7 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate { HomeViewModelFactory.self, object: HomeViewModelFactory(fetchMemorialHouseUseCase: fetchMemorialHouseUseCase) ) - } catch let error as MHError { + } catch let error as MHCoreError { MHLogger.error("\(error.description)") } catch { MHLogger.error("\(error.localizedDescription)") diff --git a/MemorialHouse/MHCore/MHCore/DIContainer.swift b/MemorialHouse/MHCore/MHCore/DIContainer.swift index a04c8915..441215b6 100644 --- a/MemorialHouse/MHCore/MHCore/DIContainer.swift +++ b/MemorialHouse/MHCore/MHCore/DIContainer.swift @@ -13,7 +13,7 @@ public final class DIContainer { let key = String(describing: type) guard let object = objects[key] as? T else { MHLogger.error("\(#function): \(key)에 해당하는 object 없음") - throw MHError.DIContainerResolveFailure(key: key) + throw MHCoreError.DIContainerResolveFailure(key: key) } return object } diff --git a/MemorialHouse/MHCore/MHCore/MHCoreError.swift b/MemorialHouse/MHCore/MHCore/MHCoreError.swift new file mode 100644 index 00000000..d61e243b --- /dev/null +++ b/MemorialHouse/MHCore/MHCore/MHCoreError.swift @@ -0,0 +1,12 @@ +import MHFoundation + +public enum MHCoreError: Error, CustomStringConvertible, Equatable { + case DIContainerResolveFailure(key: String) + + public var description: String { + switch self { + case .DIContainerResolveFailure(let key): + "\(key)에 대한 dependency resolve 실패" + } + } +} diff --git a/MemorialHouse/MHCore/MHCore/MHError.swift b/MemorialHouse/MHCore/MHCore/MHDataError.swift similarity index 81% rename from MemorialHouse/MHCore/MHCore/MHError.swift rename to MemorialHouse/MHCore/MHCore/MHDataError.swift index 98abe629..e41c68f8 100644 --- a/MemorialHouse/MHCore/MHCore/MHError.swift +++ b/MemorialHouse/MHCore/MHCore/MHDataError.swift @@ -1,7 +1,6 @@ -import Foundation +import MHFoundation -public enum MHError: Error, CustomStringConvertible, Equatable { - case DIContainerResolveFailure(key: String) +public enum MHDataError: Error, CustomStringConvertible, Equatable { case convertDTOFailure case fetchFaliure case findEntityFailure @@ -15,8 +14,6 @@ public enum MHError: Error, CustomStringConvertible, Equatable { public var description: String { switch self { - case .DIContainerResolveFailure(let key): - "\(key)에 대한 dependency resolve 실패" case .convertDTOFailure: "Entity에 대한 DTO 변환 실패" case .fetchFaliure: diff --git a/MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift index 6166ba8a..8739eb42 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift @@ -2,8 +2,8 @@ import MHFoundation import MHCore public protocol BookCoverStorage { - func create(data: BookCoverDTO) async -> Result - func fetch() async -> Result<[BookCoverDTO], MHError> - func update(with id: UUID, data: BookCoverDTO) async -> Result - func delete(with id: UUID) async -> Result + func create(data: BookCoverDTO) async -> Result + func fetch() async -> Result<[BookCoverDTO], MHDataError> + func update(with id: UUID, data: BookCoverDTO) async -> Result + func delete(with id: UUID) async -> Result } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift index b536d295..46e20f92 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift @@ -2,8 +2,8 @@ import MHFoundation import MHCore public protocol BookStorage { - func create(data: BookDTO) async -> Result - func fetch(with id: UUID) async -> Result - func update(with id: UUID, data: BookDTO) async -> Result - func delete(with id: UUID) async -> Result + func create(data: BookDTO) async -> Result + func fetch(with id: UUID) async -> Result + func update(with id: UUID, data: BookDTO) async -> Result + func delete(with id: UUID) async -> Result } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift index b65b017d..7a7e06fa 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift @@ -11,7 +11,7 @@ final class CoreDataBookCoverStorage { } extension CoreDataBookCoverStorage: BookCoverStorage { - func create(data: BookCoverDTO) async -> Result { + func create(data: BookCoverDTO) async -> Result { let context = coreDataStorage.persistentContainer.viewContext guard let entity = NSEntityDescription.entity(forEntityName: "BookCoverEntity", in: context) else { return .failure(.DIContainerResolveFailure(key: "BookCoverEntity")) @@ -28,7 +28,7 @@ extension CoreDataBookCoverStorage: BookCoverStorage { return .success(()) } - func fetch() async -> Result<[BookCoverDTO], MHError> { + func fetch() async -> Result<[BookCoverDTO], MHDataError> { let context = coreDataStorage.persistentContainer.viewContext let request = BookCoverEntity.fetchRequest() @@ -43,7 +43,7 @@ extension CoreDataBookCoverStorage: BookCoverStorage { } } - func update(with id: UUID, data: BookCoverDTO) async -> Result { + func update(with id: UUID, data: BookCoverDTO) async -> Result { do { let context = coreDataStorage.persistentContainer.viewContext guard let newEntity = try getEntityByIdentifier(in: context, with: id) else { @@ -63,7 +63,7 @@ extension CoreDataBookCoverStorage: BookCoverStorage { } } - func delete(with id: UUID) async -> Result { + func delete(with id: UUID) async -> Result { do { let context = coreDataStorage.persistentContainer.viewContext guard let entity = try getEntityByIdentifier(in: context, with: id) else { diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index 831db538..ac07f8cd 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -11,7 +11,7 @@ final class CoreDataBookStorage { } extension CoreDataBookStorage: BookStorage { - func create(data: BookDTO) async -> Result { + func create(data: BookDTO) async -> Result { let context = coreDataStorage.persistentContainer.viewContext guard let entity = NSEntityDescription.entity(forEntityName: "BookEntity", in: context) else { return .failure(.DIContainerResolveFailure(key: "BookEntity")) @@ -24,7 +24,7 @@ extension CoreDataBookStorage: BookStorage { await coreDataStorage.saveContext() return .success(()) } - func fetch(with id: UUID) async -> Result { + func fetch(with id: UUID) async -> Result { let context = coreDataStorage.persistentContainer.viewContext do { @@ -40,7 +40,7 @@ extension CoreDataBookStorage: BookStorage { return .failure(.findEntityFailure) } } - func update(with id: UUID, data: BookDTO) async -> Result { + func update(with id: UUID, data: BookDTO) async -> Result { do { let context = coreDataStorage.persistentContainer.viewContext guard let newEntity = try getEntityByIdentifier(in: context, with: id) else { @@ -55,7 +55,7 @@ extension CoreDataBookStorage: BookStorage { return .failure(.findEntityFailure) } } - func delete(with id: UUID) async -> Result { + func delete(with id: UUID) async -> Result { do { let context = coreDataStorage.persistentContainer.viewContext guard let entity = try getEntityByIdentifier(in: context, with: id) else { diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift index 41dda3e3..4294e354 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift @@ -1,6 +1,5 @@ import MHFoundation import MHCore -//import MHDomain struct MHFileManager { private let fileManager = FileManager.default @@ -12,7 +11,7 @@ struct MHFileManager { } extension MHFileManager: FileStorage { - func create(at path: String, fileName name: String, data: Data) async -> Result { + func create(at path: String, fileName name: String, data: Data) async -> Result { guard let directory = fileManager.urls( for: directoryType, in: .userDomainMask @@ -29,7 +28,7 @@ extension MHFileManager: FileStorage { return .failure(.fileCreationFailure) } } - func read(at path: String, fileName name: String) async -> Result { + func read(at path: String, fileName name: String) async -> Result { guard let directory = fileManager.urls( for: directoryType, in: .userDomainMask @@ -48,7 +47,7 @@ extension MHFileManager: FileStorage { return .failure(.fileReadingFailure) } } - func delete(at path: String, fileName name: String) async -> Result { + func delete(at path: String, fileName name: String) async -> Result { guard let directory = fileManager.urls( for: directoryType, in: .userDomainMask @@ -64,7 +63,7 @@ extension MHFileManager: FileStorage { return .failure(.fileDeletionFailure) } } - func copy(at url: URL, to newPath: String, newFileName name: String) async -> Result { + func copy(at url: URL, to newPath: String, newFileName name: String) async -> Result { let originDataPath = url guard fileManager.fileExists(atPath: originDataPath.path) else { @@ -87,7 +86,7 @@ extension MHFileManager: FileStorage { return .failure(.fileMovingFailure) } } - func copy(at path: String, fileName name: String, to newPath: String) async -> Result { + func copy(at path: String, fileName name: String, to newPath: String) async -> Result { guard let originDirectory = fileManager.urls( for: directoryType, in: .userDomainMask @@ -116,7 +115,7 @@ extension MHFileManager: FileStorage { return .failure(.fileMovingFailure) } } - func move(at path: String, fileName name: String, to newPath: String) async -> Result { + func move(at path: String, fileName name: String, to newPath: String) async -> Result { guard let originDirectory = fileManager.urls( for: directoryType, in: .userDomainMask @@ -145,7 +144,7 @@ extension MHFileManager: FileStorage { return .failure(.fileMovingFailure) } } - func moveAll(in path: String, to newPath: String) async -> Result { + func moveAll(in path: String, to newPath: String) async -> Result { guard let originDirectory = fileManager.urls( for: directoryType, in: .userDomainMask @@ -175,7 +174,7 @@ extension MHFileManager: FileStorage { return .failure(.fileMovingFailure) } } - func getURL(at path: String, fileName name: String) async -> Result { + func getURL(at path: String, fileName name: String) async -> Result { guard let originDirectory = fileManager.urls( for: directoryType, in: .userDomainMask diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift index a01987dd..54d5ec34 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift @@ -11,7 +11,7 @@ public protocol FileStorage { /// - name: Documents/{path}/{name} 이런식으로 저장됩니다. (확장자 명시 필요) /// - data: 실제 저장될 데이터 /// - Returns: 성공여부를 반환합니다. - func create(at path: String, fileName name: String, data: Data) async -> Result + func create(at path: String, fileName name: String, data: Data) async -> Result /// 지정된 경로의 파일을 읽어옵니다. /// Documents폴더에서 파일을 읽어옵니다 @@ -19,7 +19,7 @@ public protocol FileStorage { /// - path: Documents/{path} 이런식으로 들어갑니다. /// - name: Documents/{path}/{name} 이런식으로 읽어옵니다. (확장자 명시 필요) /// - Returns: 파일 데이터를 반환합니다. - func read(at path: String, fileName name: String) async -> Result + func read(at path: String, fileName name: String) async -> Result /// 지정된 경로의 파일을 삭제합니다. /// Documents폴더에서 파일을 삭제합니다. @@ -27,7 +27,7 @@ public protocol FileStorage { /// - path: Documents/{path} 이런식으로 들어갑니다. /// - name: Documents/{path}/{name} 이런식으로 삭제합니다. (확장자 명시 필요) /// - Returns: 성공여부를 반환합니다. - func delete(at path: String, fileName name: String) async -> Result + func delete(at path: String, fileName name: String) async -> Result /// 지정된 경로의 파일을 새로운 파일 이름으로 복사합니다. /// 지정된 경로 -> Documents폴더로 파일을 복사합니다. @@ -36,7 +36,7 @@ public protocol FileStorage { /// - newPath: Documents/{newPath} 이런식으로 들어갑니다. /// - name: Documents/{newPath}/{name} 이런식으로 저장됩니다. (확장자 명시 필요) /// - Returns: 성공여부를 반환합니다. - func copy(at url: URL, to newPath: String, newFileName name: String) async -> Result + func copy(at url: URL, to newPath: String, newFileName name: String) async -> Result /// 지정된 경로의 파일을 복사합니다. /// Documents폴더 -> Documents폴더로 파일을 복사합니다. @@ -46,7 +46,7 @@ public protocol FileStorage { /// - name: Documents/{path}/{name} 이 파일을 복사합니다. (확장자 명시 필요) /// - newPath: Documents/{newPath}/{name} 으로 저장합니다. /// - Returns: 성공여부를 반환합니다. - func copy(at path: String, fileName name: String, to newPath: String) async -> Result + func copy(at path: String, fileName name: String, to newPath: String) async -> Result /// 지정된 경로의 파일을 이동합니다. /// - Parameters: @@ -54,14 +54,14 @@ public protocol FileStorage { /// - name: Documents/{path}/{name} 이 파일을 이동합니다. (확장자 명시 필요) /// - newPath: Documents/{newPath}/{name} 으로 이동합니다. /// - Returns: 성공여부를 반환합니다. - func move(at path: String, fileName name: String, to newPath: String) async -> Result + func move(at path: String, fileName name: String, to newPath: String) async -> Result /// 지정된 경로의 모든 파일을 이동합니다. /// - Parameters: /// - path: Documents/{path} 이런식으로 들어갑니다 /// - newPath: Documents/{newPath} 으로 이동합니다. /// - Returns: 성공여부를 반환합니다. - func moveAll(in path: String, to newPath: String) async -> Result + func moveAll(in path: String, to newPath: String) async -> Result /// 지정된 경로의 로컬 파일 URL을 반환합니다. /// Documents폴더기준으로 파일 URL을 반환합니다. @@ -69,5 +69,5 @@ public protocol FileStorage { /// - path: Documents/{path} 이런식으로 들어갑니다 /// - name: Documents/{path}/{name} 이 파일 URL을 반환합니다. (확장자 명시 필요) /// - Returns: 파일 URL을 반환합니다. - func getURL(at path: String, fileName name: String) async -> Result + func getURL(at path: String, fileName name: String) async -> Result } diff --git a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift index 72ad49c0..b16ae2a4 100644 --- a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift +++ b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift @@ -9,12 +9,12 @@ public struct LocalBookRepository: BookRepository { self.storage = storage } - public func create(book: Book) async -> Result { + public func create(book: Book) async -> Result { let bookDTO = mappingBookToDTO(book) return await storage.create(data: bookDTO) } - public func fetch(bookID id: UUID) async -> Result { + public func fetch(bookID id: UUID) async -> Result { let result = await storage.fetch(with: id) switch result { @@ -25,12 +25,12 @@ public struct LocalBookRepository: BookRepository { return .failure(failure) } } - public func update(bookID id: UUID, to book: Book) async -> Result { + public func update(bookID id: UUID, to book: Book) async -> Result { let bookDTO = mappingBookToDTO(book) return await storage.update(with: id, data: bookDTO) } - public func delete(bookID id: UUID) async -> Result { + public func delete(bookID id: UUID) async -> Result { return await storage.delete(with: id) } diff --git a/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift index f775b7b9..005cdb8e 100644 --- a/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift +++ b/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift @@ -12,7 +12,7 @@ public struct LocalMediaRepository: MediaRepository { self.storage = storage } - public func create(media mediaDescription: MediaDescription, data: Data, to bookID: UUID?) async -> Result { + public func create(media mediaDescription: MediaDescription, data: Data, to bookID: UUID?) async -> Result { let path = bookID == nil ? "temp" : bookID!.uuidString @@ -20,7 +20,7 @@ public struct LocalMediaRepository: MediaRepository { return await storage.create(at: path, fileName: fileName, data: data) } - public func create(media mediaDescription: MediaDescription, from: URL, to bookID: UUID?) async -> Result { + public func create(media mediaDescription: MediaDescription, from: URL, to bookID: UUID?) async -> Result { let path = bookID == nil ? "temp" : bookID!.uuidString @@ -28,7 +28,7 @@ public struct LocalMediaRepository: MediaRepository { return await storage.copy(at: from, to: path, newFileName: fileName) } - public func read(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result { + public func read(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result { let path = bookID == nil ? "temp" : bookID!.uuidString @@ -36,7 +36,7 @@ public struct LocalMediaRepository: MediaRepository { return await storage.read(at: path, fileName: fileName) } - public func getURL(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result { + public func getURL(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result { let path = bookID == nil ? "temp" : bookID!.uuidString @@ -44,7 +44,7 @@ public struct LocalMediaRepository: MediaRepository { return await storage.getURL(at: path, fileName: fileName) } - public func delete(media mediaDescription: MediaDescription, at bookID: UUID?) async -> Result { + public func delete(media mediaDescription: MediaDescription, at bookID: UUID?) async -> Result { let path = bookID == nil ? "temp" : bookID!.uuidString @@ -52,13 +52,13 @@ public struct LocalMediaRepository: MediaRepository { return await storage.delete(at: path, fileName: fileName) } - public func moveTemporaryMedia(_ mediaDescription: MediaDescription, to bookID: UUID) async -> Result { + public func moveTemporaryMedia(_ mediaDescription: MediaDescription, to bookID: UUID) async -> Result { let path = bookID.uuidString let fileName = mediaDescription.id.uuidString return await storage.move(at: "temp", fileName: fileName, to: path) } - public func moveAllTemporaryMedia(to bookID: UUID) async -> Result { + public func moveAllTemporaryMedia(to bookID: UUID) async -> Result { let path = bookID.uuidString return await storage.moveAll(in: "temp", to: path) diff --git a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift index 26a129c9..90764717 100644 --- a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift +++ b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift @@ -2,8 +2,8 @@ import MHFoundation import MHCore public protocol BookRepository { - func create(book: Book) async -> Result - func fetch(bookID id: UUID) async -> Result - func update(bookID id: UUID, to book: Book) async -> Result - func delete(bookID id: UUID) async -> Result + func create(book: Book) async -> Result + func fetch(bookID id: UUID) async -> Result + func update(bookID id: UUID, to book: Book) async -> Result + func delete(bookID id: UUID) async -> Result } diff --git a/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift b/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift index 0c36f704..b6756919 100644 --- a/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift +++ b/MemorialHouse/MHDomain/MHDomain/Repository/MediaRepository.swift @@ -3,11 +3,11 @@ import MHCore import Photos public protocol MediaRepository { - func create(media mediaDescription: MediaDescription, data: Data, to bookID: UUID?) async -> Result - func create(media mediaDescription: MediaDescription, from: URL, to bookID: UUID?) async -> Result - func read(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result - func getURL(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result - func delete(media mediaDescription: MediaDescription, at bookID: UUID?) async -> Result - func moveTemporaryMedia(_ mediaDescription: MediaDescription, to bookID: UUID) async -> Result - func moveAllTemporaryMedia(to bookID: UUID) async -> Result + func create(media mediaDescription: MediaDescription, data: Data, to bookID: UUID?) async -> Result + func create(media mediaDescription: MediaDescription, from: URL, to bookID: UUID?) async -> Result + func read(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result + func getURL(media mediaDescription: MediaDescription, from bookID: UUID?) async -> Result + func delete(media mediaDescription: MediaDescription, at bookID: UUID?) async -> Result + func moveTemporaryMedia(_ mediaDescription: MediaDescription, to bookID: UUID) async -> Result + func moveAllTemporaryMedia(to bookID: UUID) async -> Result } From ab06643d67f40f3fbff57fe577116138103b57f2 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 20:43:11 +0900 Subject: [PATCH 34/44] =?UTF-8?q?chore:=20Lint=EA=B2=BD=EA=B3=A0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/MHData/Repository/LocalMediaRepository.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift index 005cdb8e..7f641528 100644 --- a/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift +++ b/MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift @@ -5,7 +5,6 @@ import MHCore import AVFoundation public struct LocalMediaRepository: MediaRepository { - private let storage: FileStorage public init(storage: FileStorage) { From 02d6543266288afef2788252d4b8a2d26d1f7372 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 22:13:37 +0900 Subject: [PATCH 35/44] =?UTF-8?q?feat:=20MediaDescription=EC=97=90=20attri?= =?UTF-8?q?bute=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/DTO/MediaDescriptionDTO.swift | 8 ++++-- .../CoreData/CoreDataBookStorage.swift | 4 ++- .../MemorialHouseModel.xcdatamodel/contents | 3 +- .../Repository/LocalBookRepository.swift | 5 +++- .../CoreDataBookStorageTests.swift | 28 +++++++++---------- .../MHDomain/Entity/MediaDescription.swift | 7 +++-- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift index 9c623a45..41acab1d 100644 --- a/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/MediaDescriptionDTO.swift @@ -4,18 +4,22 @@ import MHDomain public struct MediaDescriptionDTO { let id: UUID let type: String + let attributes: Data? - public init(id: UUID, type: String) { + public init(id: UUID, type: String, attributes: Data?) { self.id = id self.type = type + self.attributes = attributes } func toMediaDescription() -> MediaDescription? { guard let type = MediaType(rawValue: self.type) else { return nil } + let attributes = try? JSONSerialization.jsonObject(with: attributes ?? Data(), options: []) as? [String: any Sendable] return MediaDescription( id: self.id, - type: type + type: type, + attributes: attributes ) } } diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index ac07f8cd..4f825770 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -127,7 +127,8 @@ extension CoreDataBookStorage { let location = mediaDescription.location return (Int(location), MediaDescriptionDTO( id: id, - type: type + type: type, + attributes: mediaDescription.attributes )) } @@ -174,6 +175,7 @@ extension CoreDataBookStorage { entity.id = mediaDescription.id entity.type = mediaDescription.type + entity.attributes = mediaDescription.attributes entity.location = Int64(location) return entity diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents index 18959f6f..4458dde4 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/MemorialHouseModel.xcdatamodeld/MemorialHouseModel.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -13,6 +13,7 @@ + diff --git a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift index b16ae2a4..b5762b7b 100644 --- a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift +++ b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift @@ -52,9 +52,12 @@ public struct LocalBookRepository: BookRepository { ) } private func mappingMediaDescriptionToDTO(_ description: MediaDescription) -> MediaDescriptionDTO { + let attributes = try? JSONSerialization.data(withJSONObject: description.attributes ?? [:], options: []) + return MediaDescriptionDTO( id: description.id, - type: description.type.rawValue + type: description.type.rawValue, + attributes: attributes ) } } diff --git a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift index 404447b0..9115013e 100644 --- a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift +++ b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift @@ -14,21 +14,21 @@ struct CoreDataBookStorageTests { PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "image") + 0: MediaDescriptionDTO(id: UUID(), type: "image", attributes: nil) ], text: "first page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "video") + 0: MediaDescriptionDTO(id: UUID(), type: "video", attributes: nil) ], text: "second page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "audio") + 0: MediaDescriptionDTO(id: UUID(), type: "audio", attributes: nil) ], text: "third page" ) @@ -40,21 +40,21 @@ struct CoreDataBookStorageTests { PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "image") + 0: MediaDescriptionDTO(id: UUID(), type: "image", attributes: nil) ], text: "first page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "video") + 0: MediaDescriptionDTO(id: UUID(), type: "video", attributes: nil) ], text: "second page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "audio") + 0: MediaDescriptionDTO(id: UUID(), type: "audio", attributes: nil) ], text: "third page" ) @@ -75,21 +75,21 @@ struct CoreDataBookStorageTests { PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "image") + 0: MediaDescriptionDTO(id: UUID(), type: "image", attributes: nil) ], text: "first page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "video") + 0: MediaDescriptionDTO(id: UUID(), type: "video", attributes: nil) ], text: "second page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "audio") + 0: MediaDescriptionDTO(id: UUID(), type: "audio", attributes: nil) ], text: "third page" ) @@ -132,29 +132,29 @@ struct CoreDataBookStorageTests { PageDTO( id: oldBook.pages[0].id, metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "image") + 0: MediaDescriptionDTO(id: UUID(), type: "image", attributes: nil) ], text: "first page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "image"), - 2: MediaDescriptionDTO(id: UUID(), type: "image") + 0: MediaDescriptionDTO(id: UUID(), type: "image", attributes: nil), + 2: MediaDescriptionDTO(id: UUID(), type: "image", attributes: nil) ], text: "second page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "audio") + 0: MediaDescriptionDTO(id: UUID(), type: "audio", attributes: nil) ], text: "third page" ), PageDTO( id: UUID(), metadata: [ - 0: MediaDescriptionDTO(id: UUID(), type: "video") + 0: MediaDescriptionDTO(id: UUID(), type: "video", attributes: nil) ], text: "fourth page" ) diff --git a/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift b/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift index 63627fc4..d55fd33a 100644 --- a/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift +++ b/MemorialHouse/MHDomain/MHDomain/Entity/MediaDescription.swift @@ -3,12 +3,15 @@ import Foundation public struct MediaDescription: Identifiable, Sendable { public let id: UUID public let type: MediaType + public let attributes: [String: any Sendable]? public init( - id: UUID = .init(), - type: MediaType + id: UUID, + type: MediaType, + attributes: [String: any Sendable]? = nil ) { self.id = id self.type = type + self.attributes = attributes } } From 731c81d797f4d8dd7bd92d9f418564c482f4eb8d Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 22:14:22 +0900 Subject: [PATCH 36/44] =?UTF-8?q?fix:=20CoreData=EB=8F=99=EC=8B=9C?= =?UTF-8?q?=EC=84=B1=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreData/CoreDataBookStorage.swift | 93 +++++++++++++------ 1 file changed, 63 insertions(+), 30 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index 4f825770..4e5037a1 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -11,63 +11,96 @@ final class CoreDataBookStorage { } extension CoreDataBookStorage: BookStorage { - func create(data: BookDTO) async -> Result { + func create(data: BookDTO) async -> Result { let context = coreDataStorage.persistentContainer.viewContext - guard let entity = NSEntityDescription.entity(forEntityName: "BookEntity", in: context) else { - return .failure(.DIContainerResolveFailure(key: "BookEntity")) + do { + try await context.perform { [weak self] in + guard let self else { return } + guard let entity = NSEntityDescription.entity(forEntityName: "BookEntity", in: context) else { + throw MHDataError.noSuchEntity(key: "BookEntity") + } + let book = NSManagedObject(entity: entity, insertInto: context) + book.setValue(data.id, forKey: "id") + book.setValue(dtoPagesToCore(data.pages), forKey: "pages") + try context.save() + } + + return .success(()) + } catch let error as MHDataError { + MHLogger.debug("Error creating book: \(error.description)") + return .failure(error) + } catch { + MHLogger.debug("Unknown Error creating book: \(error.localizedDescription)") + return .failure(.createEntityFailure) } - - let book = NSManagedObject(entity: entity, insertInto: context) - book.setValue(data.id, forKey: "id") - book.setValue(dtoPagesToCore(data.pages), forKey: "pages") - - await coreDataStorage.saveContext() - return .success(()) } func fetch(with id: UUID) async -> Result { let context = coreDataStorage.persistentContainer.viewContext do { - guard let bookEntity = try getEntityByIdentifier(in: context, with: id) - else { return .failure(.findEntityFailure) } + var bookEntity: BookEntity? + try await context.perform { [weak self] in + guard let self else { return } + bookEntity = try getEntityByIdentifier(in: context, with: id) + guard bookEntity != nil else { throw MHDataError.findEntityFailure } + } - guard let result = coreBookToDTO(bookEntity) - else { return .failure(.convertDTOFailure) } + guard let bookEntity, + let result = coreBookToDTO(bookEntity) + else { throw MHDataError.convertDTOFailure } return .success(result) + } catch let error as MHDataError { + MHLogger.debug("Error fetching book: \(error.description)") + return .failure(error) } catch { - MHLogger.debug("Error fetching book: \(error.localizedDescription)") - return .failure(.findEntityFailure) + MHLogger.debug("Unknown Error fetching book: \(error.localizedDescription)") + return .failure(.fetchEntityFaliure) } } func update(with id: UUID, data: BookDTO) async -> Result { do { let context = coreDataStorage.persistentContainer.viewContext - guard let newEntity = try getEntityByIdentifier(in: context, with: id) else { - return .failure(.findEntityFailure) + try await context.perform { [weak self] in + guard let self else { return } + guard let newEntity = try getEntityByIdentifier(in: context, with: id) else { + throw MHDataError.findEntityFailure + } + + newEntity.setValue(data.id, forKey: "id") + newEntity.setValue(dtoPagesToCore(data.pages), forKey: "pages") + + try context.save() } - newEntity.setValue(data.id, forKey: "id") - newEntity.setValue(dtoPagesToCore(data.pages), forKey: "pages") - - await coreDataStorage.saveContext() return .success(()) + } catch let error as MHDataError { + MHLogger.debug("Error update book: \(error.description)") + return .failure(error) } catch { - return .failure(.findEntityFailure) + MHLogger.debug("Unknown Error update book: \(error.localizedDescription)") + return .failure(.updateEntityFailure) } } func delete(with id: UUID) async -> Result { do { let context = coreDataStorage.persistentContainer.viewContext - guard let entity = try getEntityByIdentifier(in: context, with: id) else { - return .failure(.findEntityFailure) + try await context.perform { [weak self] in + guard let self else { return } + guard let entity = try getEntityByIdentifier(in: context, with: id) else { + throw MHDataError.findEntityFailure + } + + context.delete(entity) + + try context.save() } - - context.delete(entity) - - await coreDataStorage.saveContext() return .success(()) + } catch let error as MHDataError { + MHLogger.debug("Error delete book: \(error.description)") + return .failure(error) } catch { - return .failure(.findEntityFailure) + MHLogger.debug("Unknown Error delete book: \(error.localizedDescription)") + return .failure(.deleteEntityFailure) } } From b8abbc95e350a90664a572ebc59962b85edc87c5 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 22:14:55 +0900 Subject: [PATCH 37/44] =?UTF-8?q?refactor:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=9C=A0=ED=98=95=20=EC=B6=94=EA=B0=80/=EA=B5=AC=EC=B2=B4?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHCore/MHCore/MHDataError.swift | 18 +++++++++++++++--- MemorialHouse/MHData/MHData/DTO/PageDTO.swift | 2 +- .../MHData/LocalStorage/BookStorage.swift | 2 +- .../CoreData/CoreDataBookCoverStorage.swift | 2 +- .../Repository/LocalBookRepository.swift | 2 +- .../CoreDataBookCoverStorageTests.swift | 2 +- .../MHDataTests/CoreDataBookStorageTests.swift | 12 ++++++------ .../MHDomain/Repository/BookRepository.swift | 2 +- 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/MemorialHouse/MHCore/MHCore/MHDataError.swift b/MemorialHouse/MHCore/MHCore/MHDataError.swift index e41c68f8..aebae2c2 100644 --- a/MemorialHouse/MHCore/MHCore/MHDataError.swift +++ b/MemorialHouse/MHCore/MHCore/MHDataError.swift @@ -1,8 +1,12 @@ import MHFoundation public enum MHDataError: Error, CustomStringConvertible, Equatable { + case noSuchEntity(key: String) + case createEntityFailure case convertDTOFailure - case fetchFaliure + case fetchEntityFaliure + case updateEntityFailure + case deleteEntityFailure case findEntityFailure case saveContextFailure case directorySettingFailure @@ -14,10 +18,18 @@ public enum MHDataError: Error, CustomStringConvertible, Equatable { public var description: String { switch self { + case let .noSuchEntity(key): + "\(key)에 대한 Entity가 존재하지 않습니다" + case .createEntityFailure: + "Entity 생성 실패" case .convertDTOFailure: "Entity에 대한 DTO 변환 실패" - case .fetchFaliure: - "Entity Fetch 실패" + case .fetchEntityFaliure: + "Entity 가져오기 실패" + case .updateEntityFailure: + "Entity 업데이트 실패" + case .deleteEntityFailure: + "Entity 삭제 실패" case .findEntityFailure: "Entity 찾기 실패" case .saveContextFailure: diff --git a/MemorialHouse/MHData/MHData/DTO/PageDTO.swift b/MemorialHouse/MHData/MHData/DTO/PageDTO.swift index c73cf2e1..d31b0418 100644 --- a/MemorialHouse/MHData/MHData/DTO/PageDTO.swift +++ b/MemorialHouse/MHData/MHData/DTO/PageDTO.swift @@ -6,7 +6,7 @@ public struct PageDTO { let metadata: [Int: MediaDescriptionDTO] let text: String - public init(id: UUID, metadata: [Int : MediaDescriptionDTO], text: String) { + public init(id: UUID, metadata: [Int: MediaDescriptionDTO], text: String) { self.id = id self.metadata = metadata self.text = text diff --git a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift index 46e20f92..bcc1e25a 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/BookStorage.swift @@ -2,7 +2,7 @@ import MHFoundation import MHCore public protocol BookStorage { - func create(data: BookDTO) async -> Result + func create(data: BookDTO) async -> Result func fetch(with id: UUID) async -> Result func update(with id: UUID, data: BookDTO) async -> Result func delete(with id: UUID) async -> Result diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift index 7a7e06fa..06ec015d 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift @@ -39,7 +39,7 @@ extension CoreDataBookCoverStorage: BookCoverStorage { return .success(result) } catch { MHLogger.debug("Error fetching book covers: \(error.localizedDescription)") - return .failure(.fetchFaliure) + return .failure(.fetchEntityFaliure) } } diff --git a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift index b5762b7b..d5f9e9fb 100644 --- a/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift +++ b/MemorialHouse/MHData/MHData/Repository/LocalBookRepository.swift @@ -9,7 +9,7 @@ public struct LocalBookRepository: BookRepository { self.storage = storage } - public func create(book: Book) async -> Result { + public func create(book: Book) async -> Result { let bookDTO = mappingBookToDTO(book) return await storage.create(data: bookDTO) diff --git a/MemorialHouse/MHData/MHDataTests/CoreDataBookCoverStorageTests.swift b/MemorialHouse/MHData/MHDataTests/CoreDataBookCoverStorageTests.swift index 64a8660e..ef6568ab 100644 --- a/MemorialHouse/MHData/MHDataTests/CoreDataBookCoverStorageTests.swift +++ b/MemorialHouse/MHData/MHDataTests/CoreDataBookCoverStorageTests.swift @@ -117,7 +117,7 @@ struct CoreDataBookCoverStorageTests { case .success: #expect(!coreDataBookCovers.contains(where: { $0.identifier == id })) case .failure(let error): - #expect(error == MHError.findEntityFailure && !coreDataBookCovers.contains(where: { $0.identifier == id })) + #expect(error == MHDataError.findEntityFailure && !coreDataBookCovers.contains(where: { $0.identifier == id })) } } } diff --git a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift index 9115013e..35d9e41f 100644 --- a/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift +++ b/MemorialHouse/MHData/MHDataTests/CoreDataBookStorageTests.swift @@ -105,7 +105,7 @@ struct CoreDataBookStorageTests { case .success: #expect(coreDataBook.id == newBook.id) case .failure(let error): - #expect(false, "Create Book 실패: \(error.localizedDescription)") + #expect(false, "Create Book 실패: \(error.description)") } } @@ -119,7 +119,7 @@ struct CoreDataBookStorageTests { case .success(let bookResult): #expect(CoreDataBookStorageTests.books.contains(where: { $0.id == bookResult.id })) case .failure(let error): - #expect(false, "Fetch Book 실패: \(error.localizedDescription)") + #expect(false, "Fetch Book 실패: \(error.description)") } } @@ -171,7 +171,7 @@ struct CoreDataBookStorageTests { let newBookResult = coreDataBook #expect(newBookResult.pages.count != oldBook.pages.count) case .failure(let error): - #expect(false, "Update Book 실패: \(error.localizedDescription)") + #expect(false, "Update Book 실패: \(error.description)") } } @@ -189,14 +189,14 @@ struct CoreDataBookStorageTests { case .success: // 삭제가 되면 성공한 거임 #expect(true) case .failure(let error): // 삭제가 실패했을 때 오류를 발생해야 함 - #expect(error == MHError.findEntityFailure) + #expect(error == MHDataError.findEntityFailure) } switch coreDataBook { case .success: // 조회가 되면 실패한 거임 - #expect(false, "Delete Book 실패: \(MHError.fetchFaliure.localizedDescription)") + #expect(false, "Delete Book 실패: \(MHDataError.fetchEntityFaliure.description)") case .failure(let error): // 조회가 실패하면 성공한 거임 - #expect(error == MHError.findEntityFailure) + #expect(error == MHDataError.findEntityFailure) } } } diff --git a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift index 90764717..15f9f067 100644 --- a/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift +++ b/MemorialHouse/MHDomain/MHDomain/Repository/BookRepository.swift @@ -2,7 +2,7 @@ import MHFoundation import MHCore public protocol BookRepository { - func create(book: Book) async -> Result + func create(book: Book) async -> Result func fetch(bookID id: UUID) async -> Result func update(bookID id: UUID, to book: Book) async -> Result func delete(bookID id: UUID) async -> Result From c23d906bbcaec5c660c47bbd1736d2413f37445c Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 22:48:26 +0900 Subject: [PATCH 38/44] =?UTF-8?q?refactor:=20Error=EC=9C=A0=ED=98=95=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift index 8739eb42..36186fb6 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/BookCoverStorage.swift @@ -2,7 +2,7 @@ import MHFoundation import MHCore public protocol BookCoverStorage { - func create(data: BookCoverDTO) async -> Result + func create(data: BookCoverDTO) async -> Result func fetch() async -> Result<[BookCoverDTO], MHDataError> func update(with id: UUID, data: BookCoverDTO) async -> Result func delete(with id: UUID) async -> Result From 88e034114379cbc62b964c1b62a698e46c388348 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 22:48:53 +0900 Subject: [PATCH 39/44] =?UTF-8?q?refactor:=20=EC=93=B8=EB=AA=A8=EC=97=86?= =?UTF-8?q?=EB=8A=94=20strong=20self=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHData/LocalStorage/CoreData/CoreDataBookStorage.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift index 4e5037a1..9f0fce1c 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookStorage.swift @@ -40,8 +40,7 @@ extension CoreDataBookStorage: BookStorage { do { var bookEntity: BookEntity? try await context.perform { [weak self] in - guard let self else { return } - bookEntity = try getEntityByIdentifier(in: context, with: id) + bookEntity = try self?.getEntityByIdentifier(in: context, with: id) guard bookEntity != nil else { throw MHDataError.findEntityFailure } } @@ -85,8 +84,7 @@ extension CoreDataBookStorage: BookStorage { do { let context = coreDataStorage.persistentContainer.viewContext try await context.perform { [weak self] in - guard let self else { return } - guard let entity = try getEntityByIdentifier(in: context, with: id) else { + guard let entity = try self?.getEntityByIdentifier(in: context, with: id) else { throw MHDataError.findEntityFailure } From 5a4f073f5fbb1e5d6bdd4d5245d17a9fe68da143 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 22:49:18 +0900 Subject: [PATCH 40/44] =?UTF-8?q?feat:=20CoreDataBookCover=EB=8F=84=20?= =?UTF-8?q?=EC=8A=A4=EB=A0=88=EB=93=9C=20=EC=84=B8=EC=9D=B4=ED=94=84...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreData/CoreDataBookCoverStorage.swift | 102 +++++++++++------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift index 06ec015d..637a6185 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift @@ -11,71 +11,97 @@ final class CoreDataBookCoverStorage { } extension CoreDataBookCoverStorage: BookCoverStorage { - func create(data: BookCoverDTO) async -> Result { + func create(data: BookCoverDTO) async -> Result { let context = coreDataStorage.persistentContainer.viewContext - guard let entity = NSEntityDescription.entity(forEntityName: "BookCoverEntity", in: context) else { - return .failure(.DIContainerResolveFailure(key: "BookCoverEntity")) + do { + try await context.perform { + guard let entity = NSEntityDescription.entity(forEntityName: "BookCoverEntity", in: context) else { + throw MHDataError.noSuchEntity(key: "BookCoverEntity") + } + let bookCover = NSManagedObject(entity: entity, insertInto: context) + bookCover.setValue(data.identifier, forKey: "identifier") + bookCover.setValue(data.title, forKey: "title") + bookCover.setValue(data.category, forKey: "category") + bookCover.setValue(data.color, forKey: "color") + bookCover.setValue(data.imageURL, forKey: "imageURL") + bookCover.setValue(data.favorite, forKey: "favorite") + + try context.save() + } + return .success(()) + } catch let error as MHDataError { + MHLogger.debug("Error creating book cover: \(error.description)") + return .failure(error) + } catch { + MHLogger.debug("Unknown Error creating book cover: \(error.localizedDescription)") + return .failure(.createEntityFailure) } - let bookCover = NSManagedObject(entity: entity, insertInto: context) - bookCover.setValue(data.identifier, forKey: "identifier") - bookCover.setValue(data.title, forKey: "title") - bookCover.setValue(data.category, forKey: "category") - bookCover.setValue(data.color, forKey: "color") - bookCover.setValue(data.imageURL, forKey: "imageURL") - bookCover.setValue(data.favorite, forKey: "favorite") - - await coreDataStorage.saveContext() - return .success(()) } func fetch() async -> Result<[BookCoverDTO], MHDataError> { let context = coreDataStorage.persistentContainer.viewContext - let request = BookCoverEntity.fetchRequest() - do { - let bookCoverEntities = try context.fetch(request) + var bookCoverEntities: [BookCoverEntity] = [] + try await context.perform { + let request = BookCoverEntity.fetchRequest() + bookCoverEntities = try context.fetch(request) + } let result = bookCoverEntities.compactMap { $0.toBookCoverDTO() } - return .success(result) + } catch let error as MHDataError { + MHLogger.debug("Error fetching book cover: \(error.description)") + return .failure(error) } catch { - MHLogger.debug("Error fetching book covers: \(error.localizedDescription)") + MHLogger.debug("Unknown Error fetching book cover: \(error.localizedDescription)") return .failure(.fetchEntityFaliure) } } func update(with id: UUID, data: BookCoverDTO) async -> Result { + let context = coreDataStorage.persistentContainer.viewContext do { - let context = coreDataStorage.persistentContainer.viewContext - guard let newEntity = try getEntityByIdentifier(in: context, with: id) else { - return .failure(.findEntityFailure) + try await context.perform { [weak self] in + guard let newEntity = try self?.getEntityByIdentifier(in: context, with: id) else { + throw MHDataError.findEntityFailure + } + newEntity.setValue(data.identifier, forKey: "identifier") + newEntity.setValue(data.title, forKey: "title") + newEntity.setValue(data.category, forKey: "category") + newEntity.setValue(data.color, forKey: "color") + newEntity.setValue(data.imageURL, forKey: "imageURL") + newEntity.setValue(data.favorite, forKey: "favorite") + + try context.save() } - newEntity.setValue(data.identifier, forKey: "identifier") - newEntity.setValue(data.title, forKey: "title") - newEntity.setValue(data.category, forKey: "category") - newEntity.setValue(data.color, forKey: "color") - newEntity.setValue(data.imageURL, forKey: "imageURL") - newEntity.setValue(data.favorite, forKey: "favorite") - - await coreDataStorage.saveContext() return .success(()) + } catch let error as MHDataError { + MHLogger.debug("Error updating book cover: \(error.description)") + return .failure(error) } catch { - return .failure(.findEntityFailure) + MHLogger.debug("Unknown Error updating book cover: \(error.localizedDescription)") + return .failure(.updateEntityFailure) } } func delete(with id: UUID) async -> Result { + let context = coreDataStorage.persistentContainer.viewContext do { - let context = coreDataStorage.persistentContainer.viewContext - guard let entity = try getEntityByIdentifier(in: context, with: id) else { - return .failure(.findEntityFailure) + try await context.perform { [weak self] in + guard let entity = try self?.getEntityByIdentifier(in: context, with: id) else { + throw MHDataError.findEntityFailure + } + + context.delete(entity) + + try context.save() } - - context.delete(entity) - - await coreDataStorage.saveContext() return .success(()) + } catch let error as MHDataError { + MHLogger.debug("Error deleting book cover: \(error.description)") + return .failure(error) } catch { - return .failure(.findEntityFailure) + MHLogger.debug("Unknown Error deleting book cover: \(error.localizedDescription)") + return .failure(.deleteEntityFailure) } } From 42332f7c16d578bb08e45628139dbf4039851c04 Mon Sep 17 00:00:00 2001 From: iceHood Date: Wed, 27 Nov 2024 23:27:14 +0900 Subject: [PATCH 41/44] =?UTF-8?q?chore:=20=EC=9E=98=EB=AA=BB=20=EC=98=AC?= =?UTF-8?q?=EB=9D=BC=EA=B0=84=EA=B1=B0=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xcschemes/MemorialHouse.xcscheme | 78 ------------------- 1 file changed, 78 deletions(-) delete mode 100644 MemorialHouse/MHApplication/MHApplication.xcodeproj/xcshareddata/xcschemes/MemorialHouse.xcscheme diff --git a/MemorialHouse/MHApplication/MHApplication.xcodeproj/xcshareddata/xcschemes/MemorialHouse.xcscheme b/MemorialHouse/MHApplication/MHApplication.xcodeproj/xcshareddata/xcschemes/MemorialHouse.xcscheme deleted file mode 100644 index 684613f1..00000000 --- a/MemorialHouse/MHApplication/MHApplication.xcodeproj/xcshareddata/xcschemes/MemorialHouse.xcscheme +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From d466ea7d3968e77924f7a14dafbf8fd554f1b41d Mon Sep 17 00:00:00 2001 From: iceHood Date: Thu, 28 Nov 2024 00:55:16 +0900 Subject: [PATCH 42/44] =?UTF-8?q?refactor:=20BookCoverDTO=EB=8F=84=20?= =?UTF-8?q?=EB=8B=A4=EB=A5=B8=20=EA=B2=83=EC=97=90=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EB=A7=9E=EC=B6=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreData/CoreDataBookCoverStorage.swift | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift index 637a6185..48ec82d0 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/CoreData/CoreDataBookCoverStorage.swift @@ -46,7 +46,7 @@ extension CoreDataBookCoverStorage: BookCoverStorage { let request = BookCoverEntity.fetchRequest() bookCoverEntities = try context.fetch(request) } - let result = bookCoverEntities.compactMap { $0.toBookCoverDTO() } + let result = bookCoverEntities.compactMap { coreBookCoverToDTO($0) } return .success(result) } catch let error as MHDataError { MHLogger.debug("Error fetching book cover: \(error.description)") @@ -112,20 +112,21 @@ extension CoreDataBookCoverStorage: BookCoverStorage { } } -// MARK: - BookCoverEntity Extension -extension BookCoverEntity { - func toBookCoverDTO() -> BookCoverDTO? { - guard let identifier = self.identifier, - let title = self.title, - let color = self.color else { return nil } +// MARK: - Mapper +extension CoreDataBookCoverStorage { + // MARK: - CoreToDTO + func coreBookCoverToDTO(_ bookCover: BookCoverEntity) -> BookCoverDTO? { + guard let identifier = bookCover.identifier, + let title = bookCover.title, + let color = bookCover.color else { return nil } return BookCoverDTO( identifier: identifier, title: title, - imageURL: self.imageURL, + imageURL: bookCover.imageURL, color: color, - category: self.category, - favorite: self.favorite + category: bookCover.category, + favorite: bookCover.favorite ) } } From 07ea62faafde49643947c7f1987fa52930d92e27 Mon Sep 17 00:00:00 2001 From: iceHood Date: Thu, 28 Nov 2024 01:11:01 +0900 Subject: [PATCH 43/44] =?UTF-8?q?chore:=20=EB=A6=B0=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift b/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift index 54d5ec34..89b2f1fe 100644 --- a/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift +++ b/MemorialHouse/MHData/MHData/LocalStorage/FileStorage.swift @@ -2,7 +2,6 @@ import MHFoundation import MHCore public protocol FileStorage { - /// 지정된 경로에 파일을 생성합니다. /// Documents폴더에 파일을 생성합니다. /// 중간 경로 폴더를 자동으로 생성합니다. From 3f198e9f1469d99f74c1f8cdb952290f2bb01bd8 Mon Sep 17 00:00:00 2001 From: iceHood Date: Thu, 28 Nov 2024 01:32:06 +0900 Subject: [PATCH 44/44] =?UTF-8?q?refactor:=20=EC=BD=94=EC=96=B4=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EB=94=B0=EB=A5=B4=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MHApplication/MHApplication/Source/App/SceneDelegate.swift | 2 +- .../MHPresentation/Source/Home/HomeViewController.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift b/MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift index e48ddf45..0253fca7 100644 --- a/MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift +++ b/MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift @@ -38,7 +38,7 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate { registerRepositoryDependency() try registerUseCaseDependency() try registerViewModelFactoryDependency() - } catch let error as MHError { + } catch let error as MHCoreError { MHLogger.error("\(error.description)") } catch { MHLogger.error("\(error.localizedDescription)") diff --git a/MemorialHouse/MHPresentation/MHPresentation/Source/Home/HomeViewController.swift b/MemorialHouse/MHPresentation/MHPresentation/Source/Home/HomeViewController.swift index de02b07a..ccf7d864 100644 --- a/MemorialHouse/MHPresentation/MHPresentation/Source/Home/HomeViewController.swift +++ b/MemorialHouse/MHPresentation/MHPresentation/Source/Home/HomeViewController.swift @@ -150,7 +150,7 @@ public final class HomeViewController: UIViewController { } self.present(navigationController, animated: true) - } catch let error as MHError { + } catch let error as MHCoreError { MHLogger.error(error.description) } catch { MHLogger.error(error.localizedDescription)