MVP: Go daemon, password auth, persistent PTY terminals, React/xterm UI, PWA
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
190604247f
commit
436732dac0
@@ -0,0 +1,71 @@
|
||||
// Package store persists small runtime state (terminal names, login sessions)
|
||||
// to a JSON file with atomic writes.
|
||||
package store
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Terminal struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type State struct {
|
||||
Terminals []Terminal `json:"terminals"`
|
||||
Sessions map[string]time.Time `json:"sessions"` // token -> expiry
|
||||
}
|
||||
|
||||
type Store struct {
|
||||
mu sync.Mutex
|
||||
path string
|
||||
state State
|
||||
}
|
||||
|
||||
func Open(path string) (*Store, error) {
|
||||
s := &Store{path: path}
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil {
|
||||
if err := json.Unmarshal(b, &s.state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if s.state.Sessions == nil {
|
||||
s.state.Sessions = map[string]time.Time{}
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Update applies fn under the lock and writes the result to disk.
|
||||
func (s *Store) Update(fn func(*State)) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
fn(&s.state)
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// View reads state under the lock.
|
||||
func (s *Store) View(fn func(*State)) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
fn(&s.state)
|
||||
}
|
||||
|
||||
func (s *Store) save() error {
|
||||
b, err := json.MarshalIndent(&s.state, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmp := s.path + ".tmp"
|
||||
if err := os.WriteFile(tmp, b, 0o600); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmp, s.path)
|
||||
}
|
||||
Reference in New Issue
Block a user