Sapling/Sources/SaplingCore/BusinessRules.swift

125 lines
4 KiB
Swift

import Foundation
public enum SaplingDomainError: Error, Equatable, Sendable {
case workspaceCannotBeInsideProject
case projectMustBeGitRepository
case subprojectPathCannotBeEmpty
}
public enum SaplingRules {
public static func validateWorkspace(_ workspace: Workspace) throws {
for item in workspace.items {
try validateWorkspaceItem(item)
}
}
public static func validateProject(_ project: Project) throws {
guard project.gitRepository.rootURL == project.repositoryURL else {
throw SaplingDomainError.projectMustBeGitRepository
}
}
public static func validateSubproject(_ subproject: Subproject) throws {
guard !subproject.path.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
throw SaplingDomainError.subprojectPathCannotBeEmpty
}
}
private static func validateWorkspaceItem(_ item: WorkspaceItem) throws {
switch item {
case .folder(let folder):
for child in folder.children {
try validateWorkspaceItem(child)
}
case .project(let project):
try validateProject(project)
case .subproject(let subproject):
try validateSubproject(subproject)
case .file:
break
}
}
}
public enum SaplingSampleData {
public static let rootURL = URL(fileURLWithPath: "/tmp/SaplingSample")
public static var document: MarkdownDocument {
MarkdownDocument(
url: rootURL.appendingPathComponent("Research/README.md"),
title: "README",
content: """
# Sapling
Sapling is a **Git-native** Markdown workspace.
- [x] Model local workspaces
- [ ] Render inactive Markdown lines
```swift
let workspace = Workspace(name: "Research", rootURL: url)
```
![Architecture](attachments/architecture.png)
"""
)
}
public static var workspace: Workspace {
let repositoryURL = rootURL.appendingPathComponent("Research")
let branch = GitBranch(name: "main", isCurrent: true, upstreamName: "origin/main")
let remote = GitRemote(
name: "origin",
url: URL(string: "https://example.com/sapling/research.git")!
)
let repository = GitRepository(
name: "Research",
rootURL: repositoryURL,
currentBranch: branch,
remotes: [remote],
statusSummary: .dirty
)
let subproject = Subproject(
name: "Shared Assets",
path: "Assets/Shared",
repositoryURL: repositoryURL.appendingPathComponent("Assets/Shared"),
remoteURL: URL(string: "https://example.com/sapling/shared-assets.git")
)
let project = Project(
name: "Research",
repositoryURL: repositoryURL,
gitRepository: repository,
remotes: [remote],
branches: [
branch,
GitBranch(name: "drafts/editor-prototype")
],
subprojects: [subproject],
usesGitLFS: true
)
return Workspace(
name: "Sapling Sample",
rootURL: rootURL,
items: [
.folder(
WorkspaceFolder(
name: "Inbox",
url: rootURL.appendingPathComponent("Inbox"),
children: [
.file(
WorkspaceFile(
name: "Scratch.md",
url: rootURL.appendingPathComponent("Inbox/Scratch.md"),
kind: .markdown
)
)
]
)
),
.project(project),
.subproject(subproject)
]
)
}
}