5bb6e89523
nib demo starts server with temp DB populated from testdata/demo.json. Covers all glyphs, card types, tags, pins, completions, deletes, and template fill placeholders.
140 lines
2.8 KiB
Go
140 lines
2.8 KiB
Go
package cmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/lerko/nib/internal/db"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var demoCmd = &cobra.Command{
|
|
Use: "demo",
|
|
Short: "start server with pre-populated demo data",
|
|
RunE: runDemo,
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(demoCmd)
|
|
}
|
|
|
|
type demoEntity struct {
|
|
Body string `json:"body"`
|
|
Glyph string `json:"glyph"`
|
|
Title *string `json:"title,omitempty"`
|
|
Description *string `json:"description,omitempty"`
|
|
TimeAnchor *string `json:"time_anchor,omitempty"`
|
|
Pinned bool `json:"pinned"`
|
|
Completed bool `json:"completed"`
|
|
Deleted bool `json:"deleted"`
|
|
CardType *string `json:"card_type,omitempty"`
|
|
CardData *string `json:"card_data,omitempty"`
|
|
Tags []string `json:"tags"`
|
|
}
|
|
|
|
func runDemo(_ *cobra.Command, _ []string) error {
|
|
tmpDir, err := os.MkdirTemp("", "nib-demo-*")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
dbPath := filepath.Join(tmpDir, "demo.db")
|
|
fmt.Printf("demo db: %s\n", dbPath)
|
|
|
|
store, err := db.Open(dbPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := seedDemo(store); err != nil {
|
|
store.Close()
|
|
return fmt.Errorf("seed demo data: %w", err)
|
|
}
|
|
store.Close()
|
|
|
|
os.Setenv("NIB_DB", dbPath)
|
|
return runServe(nil, nil)
|
|
}
|
|
|
|
func seedDemo(store *db.Store) error {
|
|
data, err := findDemoFile()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var entries []demoEntity
|
|
if err := json.Unmarshal(data, &entries); err != nil {
|
|
return fmt.Errorf("parse demo.json: %w", err)
|
|
}
|
|
|
|
now := time.Now().UTC()
|
|
for i, entry := range entries {
|
|
e := &db.Entity{
|
|
Body: entry.Body,
|
|
Glyph: db.Glyph(entry.Glyph),
|
|
Tags: entry.Tags,
|
|
}
|
|
|
|
if entry.Title != nil {
|
|
e.Title = entry.Title
|
|
}
|
|
if entry.Description != nil {
|
|
e.Description = entry.Description
|
|
}
|
|
if entry.TimeAnchor != nil {
|
|
e.TimeAnchor = entry.TimeAnchor
|
|
}
|
|
if entry.Pinned {
|
|
e.Pinned = true
|
|
}
|
|
if entry.Completed {
|
|
t := now.Add(-time.Duration(i) * time.Hour)
|
|
e.CompletedAt = &t
|
|
}
|
|
|
|
if err := store.Create(e); err != nil {
|
|
return fmt.Errorf("entity %d: %w", i, err)
|
|
}
|
|
|
|
if entry.CardType != nil {
|
|
ct := db.CardType(*entry.CardType)
|
|
if err := store.Promote(e.ID, ct, entry.CardData); err != nil {
|
|
return fmt.Errorf("promote entity %d: %w", i, err)
|
|
}
|
|
}
|
|
|
|
if entry.Deleted {
|
|
store.SoftDelete(e.ID)
|
|
}
|
|
}
|
|
|
|
fmt.Printf("seeded %d entities\n", len(entries))
|
|
return nil
|
|
}
|
|
|
|
func findDemoFile() ([]byte, error) {
|
|
candidates := []string{
|
|
"testdata/demo.json",
|
|
filepath.Join(execDir(), "testdata", "demo.json"),
|
|
}
|
|
|
|
for _, path := range candidates {
|
|
data, err := os.ReadFile(path)
|
|
if err == nil {
|
|
return data, nil
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("demo.json not found (looked in: %v)", candidates)
|
|
}
|
|
|
|
func execDir() string {
|
|
exe, err := os.Executable()
|
|
if err != nil {
|
|
return "."
|
|
}
|
|
return filepath.Dir(exe)
|
|
}
|