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:
33
internal/repository/git_repository.go
Normal file
33
internal/repository/git_repository.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GitStatus struct {
|
||||
Branch string
|
||||
Modified []string
|
||||
Untracked []string
|
||||
Staged []string
|
||||
Ahead int
|
||||
Behind int
|
||||
}
|
||||
|
||||
type Commit struct {
|
||||
Hash string
|
||||
Author string
|
||||
Date time.Time
|
||||
Message string
|
||||
Files []string
|
||||
}
|
||||
|
||||
type GitRepository interface {
|
||||
Status(ctx context.Context) (*GitStatus, error)
|
||||
Pull(ctx context.Context) error
|
||||
Push(ctx context.Context) error
|
||||
Commit(ctx context.Context, message string, files []string) error
|
||||
Log(ctx context.Context, path string, limit int) ([]*Commit, error)
|
||||
IsEnabled() bool
|
||||
Clone(ctx context.Context, url string, path string) error
|
||||
}
|
||||
40
internal/repository/graph_index.go
Normal file
40
internal/repository/graph_index.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/user/obsidian-mcp-server/internal/domain"
|
||||
)
|
||||
|
||||
type GraphNode struct {
|
||||
Path string `json:"path"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
type GraphEdge struct {
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
}
|
||||
|
||||
type GraphData struct {
|
||||
Nodes []*GraphNode `json:"nodes"`
|
||||
Edges []*GraphEdge `json:"edges"`
|
||||
}
|
||||
|
||||
type BacklinkInfo struct {
|
||||
From string `json:"from"`
|
||||
Context string `json:"context"`
|
||||
Line int `json:"line"`
|
||||
}
|
||||
|
||||
type GraphIndex interface {
|
||||
AddNote(ctx context.Context, note *domain.Note) error
|
||||
RemoveNote(ctx context.Context, path string) error
|
||||
GetBacklinks(ctx context.Context, path string) ([]*BacklinkInfo, error)
|
||||
GetOutlinks(ctx context.Context, path string) ([]string, error)
|
||||
GetConnected(ctx context.Context, path string, depth int) (*GraphData, error)
|
||||
FindBrokenLinks(ctx context.Context, notePath string) ([]string, error)
|
||||
UpdateLinks(ctx context.Context, oldPath, newPath string) error
|
||||
Rebuild(ctx context.Context, notes []*domain.Note) error
|
||||
Clear() error
|
||||
}
|
||||
18
internal/repository/note_repository.go
Normal file
18
internal/repository/note_repository.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/user/obsidian-mcp-server/internal/domain"
|
||||
)
|
||||
|
||||
type NoteRepository interface {
|
||||
Get(ctx context.Context, path string) (*domain.Note, error)
|
||||
Create(ctx context.Context, note *domain.Note) error
|
||||
Update(ctx context.Context, note *domain.Note) error
|
||||
Delete(ctx context.Context, path string) error
|
||||
List(ctx context.Context, pattern string, recursive bool) ([]*domain.Note, error)
|
||||
Exists(ctx context.Context, path string) bool
|
||||
FindByTag(ctx context.Context, tag string) ([]*domain.Note, error)
|
||||
FindByContent(ctx context.Context, query string) ([]*domain.Note, error)
|
||||
}
|
||||
36
internal/repository/search_index.go
Normal file
36
internal/repository/search_index.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/user/obsidian-mcp-server/internal/domain"
|
||||
)
|
||||
|
||||
type SearchResult struct {
|
||||
Path string `json:"path"`
|
||||
Score float64 `json:"score"`
|
||||
Matches []*SearchMatch `json:"matches"`
|
||||
}
|
||||
|
||||
type SearchMatch struct {
|
||||
Line int `json:"line"`
|
||||
Content string `json:"content"`
|
||||
ContextBefore string `json:"context_before"`
|
||||
ContextAfter string `json:"context_after"`
|
||||
}
|
||||
|
||||
type SearchQuery struct {
|
||||
Query string
|
||||
MaxResults int
|
||||
CaseSensitive bool
|
||||
UseRegex bool
|
||||
ContextLines int
|
||||
}
|
||||
|
||||
type SearchIndex interface {
|
||||
Index(ctx context.Context, note *domain.Note) error
|
||||
Remove(ctx context.Context, path string) error
|
||||
Search(ctx context.Context, query *SearchQuery) ([]*SearchResult, error)
|
||||
Rebuild(ctx context.Context, notes []*domain.Note) error
|
||||
Clear() error
|
||||
}
|
||||
30
internal/repository/tag_index.go
Normal file
30
internal/repository/tag_index.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/user/obsidian-mcp-server/internal/domain"
|
||||
)
|
||||
|
||||
type TagInfo struct {
|
||||
Name string `json:"name"`
|
||||
Count int `json:"count"`
|
||||
Nested bool `json:"nested"`
|
||||
}
|
||||
|
||||
type TagFilter struct {
|
||||
Tags []string
|
||||
Mode string // "all" or "any"
|
||||
IncludeNested bool
|
||||
}
|
||||
|
||||
type TagIndex interface {
|
||||
AddNote(ctx context.Context, note *domain.Note) error
|
||||
RemoveNote(ctx context.Context, path string) error
|
||||
GetAllTags(ctx context.Context) ([]*TagInfo, error)
|
||||
GetNotesWithTag(ctx context.Context, tag string) ([]string, error)
|
||||
GetNotesWithTags(ctx context.Context, filter *TagFilter) ([]string, error)
|
||||
RenameTag(ctx context.Context, oldTag, newTag string) error
|
||||
Rebuild(ctx context.Context, notes []*domain.Note) error
|
||||
Clear() error
|
||||
}
|
||||
39
internal/repository/vault_repository.go
Normal file
39
internal/repository/vault_repository.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/user/obsidian-mcp-server/internal/domain"
|
||||
)
|
||||
|
||||
type VaultStructure struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Type string `json:"type"` // "file" or "directory"
|
||||
Children []*VaultStructure `json:"children,omitempty"`
|
||||
}
|
||||
|
||||
type MostLinkedNote struct {
|
||||
Path string `json:"path"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type VaultStats struct {
|
||||
TotalNotes int `json:"total_notes"`
|
||||
TotalWords int `json:"total_words"`
|
||||
TotalLinks int `json:"total_links"`
|
||||
TotalTags int `json:"total_tags"`
|
||||
AvgNoteLength int `json:"avg_note_length"`
|
||||
MostLinked []*MostLinkedNote `json:"most_linked"`
|
||||
OrphanedNotes int `json:"orphaned_notes"`
|
||||
LastIndexed string `json:"last_indexed"`
|
||||
}
|
||||
|
||||
type VaultRepository interface {
|
||||
GetStats(ctx context.Context) (*VaultStats, error)
|
||||
GetStructure(ctx context.Context, maxDepth int) (*VaultStructure, error)
|
||||
FindOrphaned(ctx context.Context, excludePaths []string) ([]string, error)
|
||||
GetMostLinked(ctx context.Context, limit int) ([]*MostLinkedNote, error)
|
||||
Initialize(ctx context.Context, vault *domain.Vault) error
|
||||
Rebuild(ctx context.Context) error
|
||||
}
|
||||
Reference in New Issue
Block a user