Files
ax/src/cmd/root.go
T
eliaskohout c1f196640b
Build and Publish Arch Package / build-arch (amd64, x86_64) (push) Successful in 44s
Build and Publish Arch Package / build-arch (arm64, aarch64) (push) Successful in 49s
Build and Publish Docker Image / build-apk (amd64, x86_64) (push) Successful in 44s
Build and Publish Docker Image / build-apk (arm64, aarch64) (push) Successful in 44s
Build and Publish Docker Image / build-and-push-docker (push) Successful in 10m47s
fix: resolve AX_TOKEN before config user in getNodeService
2026-06-12 15:53:09 +02:00

138 lines
3.7 KiB
Go

package cmd
import (
"axolotl/models"
"axolotl/service"
"axolotl/store"
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
)
func getNodeService() (service.NodeService, error) {
if token := os.Getenv("AX_TOKEN"); token != "" {
if cfg.Remote.Host != "" {
base := fmt.Sprintf("http://%s:%d", cfg.Remote.Host, cfg.Remote.Port)
return service.NewRemoteNodeService(base, ""), nil
}
st, err := store.FindAndOpenSQLiteStore()
if err != nil {
return nil, err
}
agentID := service.LookupAgentToken(st, token)
if agentID == "" {
return nil, fmt.Errorf("invalid AX_TOKEN: agent not found")
}
return service.NewLocalNodeService(st, agentID), nil
}
user := cfg.User
if user == "" {
return nil, fmt.Errorf("no user configured: run 'ax user set <username>' first")
}
if cfg.Remote.Host != "" {
base := fmt.Sprintf("http://%s:%d", cfg.Remote.Host, cfg.Remote.Port)
return service.NewRemoteNodeService(base, user), nil
}
st, err := store.FindAndOpenSQLiteStore()
if err != nil {
return nil, err
}
return service.NewLocalNodeService(st, user), nil
}
var jsonFlag bool
var cfg *store.Config
var rootCmd = &cobra.Command{Use: "ax", Short: "The axolotl issue tracker"}
func Execute() {
var err error
cfg, err = store.LoadConfig()
if err != nil {
fmt.Fprintln(os.Stderr, "failed to load config:", err)
os.Exit(1)
}
RegisterAliasCommands()
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
func init() {
rootCmd.PersistentFlags().BoolVar(&jsonFlag, "json", false, "")
}
func RegisterAliasCommands() {
rootCmd.AddGroup(&cobra.Group{ID: "aliases", Title: "Aliases:"})
aliases := cfg.Aliases
for _, a := range aliases {
rootCmd.AddCommand(&cobra.Command{
Use: a.Name,
Short: a.Description,
GroupID: "aliases",
DisableFlagParsing: true,
Run: func(ccmd *cobra.Command, args []string) {
acmd := a.Command
acmd = strings.ReplaceAll(acmd, "$me", cfg.User)
parts := strings.Fields(acmd)
var expanded []string
usedArgs := make([]bool, len(args))
for _, part := range parts {
if part == "$@" {
expanded = append(expanded, args...)
for i := range usedArgs {
usedArgs[i] = true
}
continue
}
hasCatchAll := strings.Contains(part, "$@")
replaced := part
if hasCatchAll {
replaced = strings.ReplaceAll(replaced, "$@", strings.Join(args, " "))
for i := range usedArgs {
usedArgs[i] = true
}
}
for i := len(args) - 1; i >= 0; i-- {
placeholder := fmt.Sprintf("$%d", i+1)
if strings.Contains(replaced, placeholder) {
replaced = strings.ReplaceAll(replaced, placeholder, args[i])
usedArgs[i] = true
}
}
expanded = append(expanded, replaced)
}
// Forward any unconsumed args (e.g. --json flag).
for i, arg := range args {
if !usedArgs[i] {
expanded = append(expanded, arg)
}
}
rootCmd.SetArgs(expanded)
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
},
})
}
}
// parseRelInput parses a rel string into a RelInput.
// Formats:
// - "prefix::value" → property rel with no target (tag)
// - "relname:target" → edge rel with a target node
// - "tagname" → simple label rel with no target (alias for --tag)
func parseRelInput(s string) (service.RelInput, error) {
if strings.Contains(s, "::") {
// Property: name::value — no target node.
return service.RelInput{Type: models.RelType(s), Target: ""}, nil
}
if idx := strings.Index(s, ":"); idx >= 0 {
// Edge rel: relname:target.
return service.RelInput{Type: models.RelType(s[:idx]), Target: s[idx+1:]}, nil
}
// Simple label tag — no target node.
return service.RelInput{Type: models.RelType(s), Target: ""}, nil
}