Sprint 6: JSON file persistence + real SSH terminal + V1 crypto/knownhosts integration
- go.mod replace directive for git.tukangketik.id/swanadiva/hostkeeper → ../../v1 - store/ package: JSON file persistence for hosts, snippets, keys, settings (~/Library/Application Support/hostkeeper/v2/) - model SSH fields: Hostname, Port, Username, AuthType, Password, KeyID - sshconn/ package: real SSH client via golang.org/x/crypto/ssh - Terminal WS: real SSH connection with fallback to mock shell - Dynamic host list in terminal (server-rendered JSON script tag) - All mock data defaults removed from model packages - Settings persist via store/settings.go
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"time"
|
||||
"git.tukangketik.id/swanadiva/hostkeeper/v2/internal/model"
|
||||
)
|
||||
|
||||
type SnippetStore struct {
|
||||
snippets []model.Snippet
|
||||
}
|
||||
|
||||
func NewSnippetStore() *SnippetStore {
|
||||
s := &SnippetStore{}
|
||||
mu.RLock()
|
||||
readFile("snippets.json", &s.snippets)
|
||||
mu.RUnlock()
|
||||
if s.snippets == nil {
|
||||
s.snippets = []model.Snippet{}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *SnippetStore) All() []model.Snippet {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
return s.snippets
|
||||
}
|
||||
|
||||
func (s *SnippetStore) Search(q string) []model.Snippet {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
if q == "" {
|
||||
return s.snippets
|
||||
}
|
||||
var res []model.Snippet
|
||||
for _, sn := range s.snippets {
|
||||
if contains(sn.Name, q) || contains(sn.Content, q) || contains(sn.Language, q) {
|
||||
res = append(res, sn)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *SnippetStore) Add(name, content, language string, tags []string) model.Snippet {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
sn := model.Snippet{
|
||||
ID: randID(),
|
||||
Name: name,
|
||||
Content: content,
|
||||
Language: language,
|
||||
Tags: tags,
|
||||
CreatedAt: time.Now().Format("Jan 2, 2006"),
|
||||
}
|
||||
s.snippets = append(s.snippets, sn)
|
||||
writeFile("snippets.json", &s.snippets)
|
||||
return sn
|
||||
}
|
||||
|
||||
func (s *SnippetStore) Delete(id string) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
for i, sn := range s.snippets {
|
||||
if sn.ID == id {
|
||||
s.snippets = append(s.snippets[:i], s.snippets[i+1:]...)
|
||||
writeFile("snippets.json", &s.snippets)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user