main.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "os/signal"
  7. "syscall"
  8. "gogs.dmsc.dev/arp/arp_cli/cmd"
  9. "github.com/urfave/cli/v3"
  10. )
  11. func main() {
  12. // Create context with cancellation for graceful shutdown
  13. ctx, cancel := context.WithCancel(context.Background())
  14. defer cancel()
  15. // Handle interrupt signals
  16. sigChan := make(chan os.Signal, 1)
  17. signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
  18. go func() {
  19. <-sigChan
  20. cancel()
  21. }()
  22. // Build the CLI app
  23. app := buildApp()
  24. // If no arguments provided (only program name), perform login then start REPL mode
  25. if len(os.Args) <= 1 {
  26. // Create a command context for login
  27. loginCmd := &cli.Command{
  28. Name: "login",
  29. Flags: []cli.Flag{
  30. &cli.StringFlag{Name: "url"},
  31. &cli.StringFlag{Name: "email"},
  32. &cli.StringFlag{Name: "password"},
  33. },
  34. Action: cmd.LoginCommand().Action,
  35. }
  36. // Execute login command
  37. if err := loginCmd.Run(ctx, os.Args); err != nil {
  38. fmt.Fprintf(os.Stderr, "Login failed: %v\n", err)
  39. os.Exit(1)
  40. }
  41. // Start REPL mode after successful login
  42. repl := cmd.NewREPL(app)
  43. if err := repl.Run(ctx); err != nil {
  44. fmt.Fprintf(os.Stderr, "Error: %v\n", err)
  45. os.Exit(1)
  46. }
  47. return
  48. }
  49. // Otherwise, run single command mode
  50. if err := app.Run(ctx, os.Args); err != nil {
  51. fmt.Fprintf(os.Stderr, "Error: %v\n", err)
  52. os.Exit(1)
  53. }
  54. }
  55. func buildApp() *cli.Command {
  56. return &cli.Command{
  57. Name: "arp_cli",
  58. Usage: "Command-line interface for ARP (Agent-native ERP)",
  59. Description: `ARP CLI is a command-line tool for interacting with ARP GraphQL servers.
  60. It provides CRUD operations for Services, Users, Notes, Tasks, Messages,
  61. Roles, and Permissions. Real-time updates are available via WebSocket subscriptions
  62. for Tasks and Messages.
  63. When run without arguments, it starts an interactive REPL mode.
  64. Use 'exit' or 'quit' to leave the REPL, or Ctrl+D.
  65. First, login to an ARP server using 'login' to store your credentials.
  66. Then use the various commands to manage your ARP data.`,
  67. Version: "1.0.0",
  68. Flags: []cli.Flag{
  69. &cli.StringFlag{
  70. Name: "url",
  71. Aliases: []string{"u"},
  72. Usage: "ARP server URL",
  73. Sources: cli.EnvVars("ARP_URL"),
  74. },
  75. &cli.StringFlag{
  76. Name: "output",
  77. Aliases: []string{"o"},
  78. Usage: "Output format (table, json)",
  79. Value: "table",
  80. },
  81. },
  82. Commands: []*cli.Command{
  83. cmd.LoginCommand(),
  84. cmd.ConfigCommand(),
  85. cmd.ServiceCommand(),
  86. cmd.UserCommand(),
  87. cmd.NoteCommand(),
  88. cmd.TaskCommand(),
  89. cmd.MessageCommand(),
  90. cmd.RoleCommand(),
  91. cmd.PermissionCommand(),
  92. cmd.WorkflowCommand(),
  93. },
  94. Before: func(ctx context.Context, command *cli.Command) (context.Context, error) {
  95. // Store global flags in context for later use
  96. return ctx, nil
  97. },
  98. Action: func(ctx context.Context, cmd *cli.Command) error {
  99. // Show help when no subcommand is provided
  100. return cli.ShowAppHelp(cmd)
  101. },
  102. }
  103. }