Restructured the folder structure of the library target.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import Foundation
|
||||
|
||||
extension URL {
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
init(at filePath: String) {
|
||||
if #available(macOS 13.0, *) {
|
||||
self = URL(filePath: filePath)
|
||||
} else {
|
||||
self = URL(fileURLWithPath: filePath)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
var pathString: String {
|
||||
if #available(macOS 13.0, *) {
|
||||
path()
|
||||
} else {
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
func appendingPath(_ path: String) -> URL {
|
||||
if #available(macOS 13.0, *) {
|
||||
appending(path: path)
|
||||
} else {
|
||||
appendingPathComponent(path)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import Foundation
|
||||
|
||||
public protocol FileServicing {
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
var currentFolder: URL { get async }
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
func copyItem(from source: URL, to destination: URL) async throws (FileServiceError)
|
||||
func createFolder(at location: URL) async throws (FileServiceError)
|
||||
func deleteItem(at location: URL) async throws (FileServiceError)
|
||||
func isItemExists(at location: URL) async throws (FileServiceError) -> Bool
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Errors
|
||||
|
||||
public enum FileServiceError: Error, Equatable {
|
||||
case folderNotCreated
|
||||
case itemNotCopied
|
||||
case itemAlreadyExists
|
||||
case itemNotDeleted
|
||||
case itemNotExists
|
||||
case itemNotFileURL
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import Foundation
|
||||
|
||||
public struct FileService: FileServicing {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let fileManager: FileManager
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
public init(fileManager: FileManager = .default) {
|
||||
self.fileManager = fileManager
|
||||
}
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
public var currentFolder: URL {
|
||||
get async {
|
||||
.init(at: fileManager.currentDirectoryPath)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
public func copyItem(from source: URL, to destination: URL) async throws (FileServiceError) {
|
||||
guard try await isItemExists(at: source) else {
|
||||
throw FileServiceError.itemNotExists
|
||||
}
|
||||
guard try await !isItemExists(at: destination) else {
|
||||
throw FileServiceError.itemAlreadyExists
|
||||
}
|
||||
|
||||
do {
|
||||
try fileManager.copyItem(at: source, to: destination)
|
||||
} catch {
|
||||
throw FileServiceError.itemNotCopied
|
||||
}
|
||||
}
|
||||
|
||||
public func createFolder(at location: URL) async throws (FileServiceError) {
|
||||
guard try await !isItemExists(at: location) else {
|
||||
throw FileServiceError.itemAlreadyExists
|
||||
}
|
||||
|
||||
do {
|
||||
try fileManager.createDirectory(at: location, withIntermediateDirectories: true)
|
||||
} catch {
|
||||
throw FileServiceError.folderNotCreated
|
||||
}
|
||||
}
|
||||
|
||||
public func deleteItem(at location: URL) async throws (FileServiceError) {
|
||||
guard try await isItemExists(at: location) else {
|
||||
throw FileServiceError.itemNotExists
|
||||
}
|
||||
|
||||
do {
|
||||
try fileManager.removeItem(at: location)
|
||||
} catch {
|
||||
throw FileServiceError.itemNotDeleted
|
||||
}
|
||||
}
|
||||
|
||||
public func isItemExists(at location: URL) async throws (FileServiceError) -> Bool {
|
||||
guard location.isFileURL else {
|
||||
throw FileServiceError.itemNotFileURL
|
||||
}
|
||||
|
||||
let filePath = location.pathString
|
||||
|
||||
return fileManager.fileExists(atPath: filePath)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import Foundation
|
||||
|
||||
public struct CopyFilesTask {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let fileService: FileServicing
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
public init(fileService: FileServicing) {
|
||||
self.fileService = fileService
|
||||
}
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
public func callAsFunction(to rootFolder: URL) async throws {
|
||||
let filesFolder = URL(at: .folderFiles)
|
||||
|
||||
for fileToCopy in Self.filesToCopy {
|
||||
try await fileService.copyItem(
|
||||
from: filesFolder.appendingPath(fileToCopy),
|
||||
to: rootFolder.appendingPath(fileToCopy)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
extension CopyFilesTask {
|
||||
|
||||
// MARK: Constants
|
||||
|
||||
static let filesToCopy: [String] = [
|
||||
.fileDockerIgnore,
|
||||
.fileGitIgnore,
|
||||
.fileLicense,
|
||||
.fileReadme
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
// MARK: - URL+Constants
|
||||
|
||||
private extension String {
|
||||
static let folderFiles = "./Resources/Files"
|
||||
static let fileDockerIgnore = ".dockerignore"
|
||||
static let fileGitIgnore = ".gitignore"
|
||||
static let fileLicense = "LICENSE"
|
||||
static let fileReadme = "README.md"
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import Foundation
|
||||
|
||||
public struct CreateFoldersTask {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let fileService: FileServicing
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
public init(fileService: FileServicing) {
|
||||
self.fileService = fileService
|
||||
}
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
public func callAsFunction(at rootFolder: URL) async throws {
|
||||
let folders = Self.foldersToCreate.map { rootFolder.appendingPath($0) }
|
||||
|
||||
for folder in folders {
|
||||
try await fileService.createFolder(at: folder)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
extension CreateFoldersTask {
|
||||
|
||||
// MARK: Constants
|
||||
|
||||
static let foldersToCreate: [String] = [
|
||||
.folderApp,
|
||||
.folderAppInfrastructure,
|
||||
.folderAppTestCases,
|
||||
.folderAppTestSources
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
// MARK: - String+Constants
|
||||
|
||||
private extension String {
|
||||
static let folderApp = "Sources/App"
|
||||
static let folderAppInfrastructure = "Sources/AppInfrastructure"
|
||||
static let folderAppTestCases = "Tests/App/Cases"
|
||||
static let folderAppTestSources = "Tests/App/Sources"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import Foundation
|
||||
|
||||
public struct CreateRootFolderTask {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let fileService: FileServicing
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
public init(fileService: FileServicing) {
|
||||
self.fileService = fileService
|
||||
}
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
public func callAsFunction(
|
||||
name: String,
|
||||
at location: URL? = nil
|
||||
) async throws -> URL {
|
||||
guard !name.isEmpty else {
|
||||
throw CreateRootFolderError.nameIsEmpty
|
||||
}
|
||||
|
||||
let rootFolder = if let location {
|
||||
location
|
||||
} else {
|
||||
await fileService.currentFolder
|
||||
}
|
||||
|
||||
let newFolder = rootFolder.appendingPath(name)
|
||||
|
||||
try await fileService.createFolder(at: newFolder)
|
||||
|
||||
return newFolder
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Errors
|
||||
|
||||
public enum CreateRootFolderError: Error {
|
||||
case nameIsEmpty
|
||||
}
|
||||
Reference in New Issue
Block a user