feat: Implement foundation layer with domain entities and repository interfaces
- Add complete domain layer: Note, Vault, WikiLink, Tag, Frontmatter, Graph entities - Implement repository interfaces for data access abstraction - Create comprehensive configuration system with YAML and env support - Add CLI entry point with signal handling and graceful shutdown - Fix mermaid diagram syntax in design.md (array notation) - Add CLAUDE.md for development guidance 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
117
internal/domain/graph.go
Normal file
117
internal/domain/graph.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package domain
|
||||
|
||||
import "sync"
|
||||
|
||||
type Graph struct {
|
||||
adjacencyList map[string]map[string]bool
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
func NewGraph() *Graph {
|
||||
return &Graph{
|
||||
adjacencyList: make(map[string]map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) AddEdge(from, to string) {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
|
||||
if g.adjacencyList[from] == nil {
|
||||
g.adjacencyList[from] = make(map[string]bool)
|
||||
}
|
||||
g.adjacencyList[from][to] = true
|
||||
}
|
||||
|
||||
func (g *Graph) RemoveEdge(from, to string) {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
|
||||
if g.adjacencyList[from] != nil {
|
||||
delete(g.adjacencyList[from], to)
|
||||
if len(g.adjacencyList[from]) == 0 {
|
||||
delete(g.adjacencyList, from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) GetOutlinks(path string) []string {
|
||||
g.mutex.RLock()
|
||||
defer g.mutex.RUnlock()
|
||||
|
||||
var outlinks []string
|
||||
if targets, exists := g.adjacencyList[path]; exists {
|
||||
for target := range targets {
|
||||
outlinks = append(outlinks, target)
|
||||
}
|
||||
}
|
||||
return outlinks
|
||||
}
|
||||
|
||||
func (g *Graph) GetBacklinks(path string) []string {
|
||||
g.mutex.RLock()
|
||||
defer g.mutex.RUnlock()
|
||||
|
||||
var backlinks []string
|
||||
for source, targets := range g.adjacencyList {
|
||||
if targets[path] {
|
||||
backlinks = append(backlinks, source)
|
||||
}
|
||||
}
|
||||
return backlinks
|
||||
}
|
||||
|
||||
func (g *Graph) HasEdge(from, to string) bool {
|
||||
g.mutex.RLock()
|
||||
defer g.mutex.RUnlock()
|
||||
|
||||
if targets, exists := g.adjacencyList[from]; exists {
|
||||
return targets[to]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *Graph) RemoveNode(path string) {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
|
||||
delete(g.adjacencyList, path)
|
||||
|
||||
for source, targets := range g.adjacencyList {
|
||||
delete(targets, path)
|
||||
if len(targets) == 0 {
|
||||
delete(g.adjacencyList, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) GetAllNodes() []string {
|
||||
g.mutex.RLock()
|
||||
defer g.mutex.RUnlock()
|
||||
|
||||
nodeSet := make(map[string]bool)
|
||||
|
||||
for source := range g.adjacencyList {
|
||||
nodeSet[source] = true
|
||||
}
|
||||
|
||||
for _, targets := range g.adjacencyList {
|
||||
for target := range targets {
|
||||
nodeSet[target] = true
|
||||
}
|
||||
}
|
||||
|
||||
var nodes []string
|
||||
for node := range nodeSet {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (g *Graph) Clear() {
|
||||
g.mutex.Lock()
|
||||
defer g.mutex.Unlock()
|
||||
|
||||
g.adjacencyList = make(map[string]map[string]bool)
|
||||
}
|
||||
Reference in New Issue
Block a user