Add Go/Postgres admin APIs, Angular admin UI, manual build flow, asset uploads, markdown import/export, configurable slug generation, and the Yar reading theme. Exclude local docs and generated development artifacts from version control.
106 lines
2.3 KiB
Go
106 lines
2.3 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func runConfig(root string, args []string) error {
|
|
if len(args) == 0 {
|
|
return errors.New("site config is local-file-only; edit config/site.yaml directly")
|
|
}
|
|
return fmt.Errorf("site config is local-file-only; edit config/site.yaml directly (unsupported subcommand %q)", args[0])
|
|
}
|
|
|
|
func loadLocalConfig(root string) (localConfig, error) {
|
|
var config localConfig
|
|
path := filepath.Join(root, "config/local.yaml")
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return config, nil
|
|
}
|
|
return config, err
|
|
}
|
|
if err := yaml.Unmarshal(data, &config); err != nil {
|
|
return config, fmt.Errorf("%s: %w", path, err)
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func readSiteConfig(root string) (siteConfigFile, error) {
|
|
var config siteConfigFile
|
|
path := filepath.Join(root, "config/site.yaml")
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return config, err
|
|
}
|
|
if err := yaml.Unmarshal(data, &config); err != nil {
|
|
return config, fmt.Errorf("%s: %w", path, err)
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func writeSiteConfig(root string, config siteConfigFile) error {
|
|
var out bytes.Buffer
|
|
encoder := yaml.NewEncoder(&out)
|
|
encoder.SetIndent(2)
|
|
if err := encoder.Encode(config); err != nil {
|
|
return err
|
|
}
|
|
if err := encoder.Close(); err != nil {
|
|
return err
|
|
}
|
|
|
|
path := filepath.Join(root, "config/site.yaml")
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
return err
|
|
}
|
|
tmp := path + ".tmp"
|
|
if err := os.WriteFile(tmp, out.Bytes(), 0o644); err != nil {
|
|
return err
|
|
}
|
|
return os.Rename(tmp, path)
|
|
}
|
|
|
|
func defaultSiteConfig() string {
|
|
return `meta:
|
|
config_version: 1
|
|
updated_at: "2026-05-28T12:00:00+08:00"
|
|
updated_by: "cli"
|
|
|
|
site:
|
|
title: "Osaet"
|
|
description: "Personal blog"
|
|
base_url: "http://localhost:4321"
|
|
language: "zh-CN"
|
|
timezone: "Asia/Shanghai"
|
|
|
|
content:
|
|
posts_dir: "content/posts"
|
|
assets_dir: "content/assets"
|
|
|
|
build:
|
|
astro_project: "frontend/site"
|
|
output_dir: "dist/site"
|
|
`
|
|
}
|
|
|
|
func defaultLocalExampleConfig() string {
|
|
return `database:
|
|
driver: "sqlite"
|
|
sqlite_path: ".osaet/osaet.db"
|
|
postgres_dsn: ""
|
|
|
|
deepseek:
|
|
api_key: ""
|
|
api_key_env: "DEEPSEEK_API_KEY"
|
|
base_url: "https://api.deepseek.com"
|
|
model: "deepseek-v4-pro"
|
|
`
|
|
}
|