feat(cli): ninja CLI with login, plugin init/publish/status
Cobra scaffold, credentials store, Connect client, device-flow login, whoami/logout, plugin init (creates + adds git remote), publish (tag + push + registry RPC), and status (list scopes/plugins). Proto copied from orchestrator with buf codegen for client stubs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7ff326ef25
commit
7f4bce79c9
15
buf.gen.yaml
Normal file
15
buf.gen.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
version: v2
|
||||||
|
managed:
|
||||||
|
enabled: true
|
||||||
|
override:
|
||||||
|
- file_option: go_package_prefix
|
||||||
|
value: git.dev.alexdunmow.com/block/core/internal/api
|
||||||
|
plugins:
|
||||||
|
- local: protoc-gen-go
|
||||||
|
out: internal/api
|
||||||
|
opt:
|
||||||
|
- paths=source_relative
|
||||||
|
- local: protoc-gen-connect-go
|
||||||
|
out: internal/api
|
||||||
|
opt:
|
||||||
|
- paths=source_relative
|
||||||
12
buf.yaml
Normal file
12
buf.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
version: v2
|
||||||
|
modules:
|
||||||
|
- path: proto
|
||||||
|
lint:
|
||||||
|
use:
|
||||||
|
- STANDARD
|
||||||
|
except:
|
||||||
|
- PACKAGE_SAME_GO_PACKAGE
|
||||||
|
- RPC_REQUEST_RESPONSE_UNIQUE
|
||||||
|
breaking:
|
||||||
|
use:
|
||||||
|
- FILE
|
||||||
114
cmd/ninja/cmd/login.go
Normal file
114
cmd/ninja/cmd/login.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"connectrpc.com/connect"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"git.dev.alexdunmow.com/block/core/cmd/ninja/internal/creds"
|
||||||
|
"git.dev.alexdunmow.com/block/core/cmd/ninja/internal/orchclient"
|
||||||
|
v1 "git.dev.alexdunmow.com/block/core/internal/api/orchestrator/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newLoginCmd() *cobra.Command {
|
||||||
|
var host string
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "login",
|
||||||
|
Short: "Authenticate against the orchestrator using device flow",
|
||||||
|
RunE: func(c *cobra.Command, _ []string) error {
|
||||||
|
if host == "" {
|
||||||
|
host, _ = c.Flags().GetString("host")
|
||||||
|
}
|
||||||
|
if host == "" {
|
||||||
|
host = "https://my.blockninjacms.com"
|
||||||
|
}
|
||||||
|
cli := orchclient.New(host, "")
|
||||||
|
ctx := context.Background()
|
||||||
|
start, err := cli.Auth.StartDevice(ctx, connect.NewRequest(&v1.StartDeviceRequest{
|
||||||
|
Scopes: []string{"plugin:read", "plugin:publish", "scope:admin"},
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("start device: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Visit %s and enter code: %s\n", start.Msg.VerificationUri, start.Msg.UserCode)
|
||||||
|
interval := time.Duration(start.Msg.IntervalSeconds) * time.Second
|
||||||
|
deadline := time.Now().Add(time.Duration(start.Msg.ExpiresInSeconds) * time.Second)
|
||||||
|
for time.Now().Before(deadline) {
|
||||||
|
time.Sleep(interval)
|
||||||
|
poll, err := cli.Auth.PollDevice(ctx, connect.NewRequest(&v1.PollDeviceRequest{DeviceCode: start.Msg.DeviceCode}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch poll.Msg.Status {
|
||||||
|
case "pending":
|
||||||
|
continue
|
||||||
|
case "approved":
|
||||||
|
cr, err := creds.Load()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cr.DefaultHost = host
|
||||||
|
if cr.Hosts == nil {
|
||||||
|
cr.Hosts = map[string]creds.HostCreds{}
|
||||||
|
}
|
||||||
|
cr.Hosts[host] = creds.HostCreds{Token: poll.Msg.AccessToken}
|
||||||
|
if err := cr.Save(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("Logged in.")
|
||||||
|
return nil
|
||||||
|
case "expired":
|
||||||
|
return fmt.Errorf("device code expired; try again")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("login timed out")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmd.Flags().StringVar(&host, "host", "", "Orchestrator base URL")
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newWhoamiCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "whoami",
|
||||||
|
Short: "Show the currently logged-in user",
|
||||||
|
RunE: func(c *cobra.Command, _ []string) error {
|
||||||
|
host, _ := c.Flags().GetString("host")
|
||||||
|
cr, err := creds.Load()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resolvedHost, hc, err := cr.Resolve(host)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cli := orchclient.New(resolvedHost, hc.Token)
|
||||||
|
r, err := cli.Auth.Whoami(context.Background(), connect.NewRequest(&v1.WhoamiRequest{}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("%s <%s> at %s\n", r.Msg.DisplayName, r.Msg.Email, resolvedHost)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLogoutCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "logout",
|
||||||
|
Short: "Remove stored credentials",
|
||||||
|
RunE: func(c *cobra.Command, _ []string) error {
|
||||||
|
host, _ := c.Flags().GetString("host")
|
||||||
|
cr, err := creds.Load()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resolvedHost, _, _ := cr.Resolve(host)
|
||||||
|
delete(cr.Hosts, resolvedHost)
|
||||||
|
return cr.Save()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
236
cmd/ninja/cmd/plugin.go
Normal file
236
cmd/ninja/cmd/plugin.go
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"connectrpc.com/connect"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
core "git.dev.alexdunmow.com/block/core/plugin"
|
||||||
|
|
||||||
|
"git.dev.alexdunmow.com/block/core/cmd/ninja/internal/creds"
|
||||||
|
"git.dev.alexdunmow.com/block/core/cmd/ninja/internal/orchclient"
|
||||||
|
v1 "git.dev.alexdunmow.com/block/core/internal/api/orchestrator/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newPluginCmd() *cobra.Command {
|
||||||
|
c := &cobra.Command{Use: "plugin", Short: "Manage BlockNinja plugins"}
|
||||||
|
c.AddCommand(newPluginInitCmd(), newPluginPublishCmd(), newPluginStatusCmd())
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPluginInitCmd() *cobra.Command {
|
||||||
|
var scope, name string
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "init",
|
||||||
|
Short: "Create a plugin in the registry and add a git remote",
|
||||||
|
RunE: func(c *cobra.Command, _ []string) error {
|
||||||
|
host, _ := c.Flags().GetString("host")
|
||||||
|
cr, err := creds.Load()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resolvedHost, hc, err := cr.Resolve(host)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cli := orchclient.New(resolvedHost, hc.Token)
|
||||||
|
|
||||||
|
scope = strings.TrimPrefix(scope, "@")
|
||||||
|
if scope == "" || name == "" {
|
||||||
|
return fmt.Errorf("usage: ninja plugin init --scope ACME --name foo")
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
resp, err := cli.Reg.CreatePlugin(ctx, connect.NewRequest(&v1.CreatePluginRequest{
|
||||||
|
ScopeSlug: scope, Name: name, Description: "",
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("Created @%s/%s\n", scope, name)
|
||||||
|
fmt.Printf(" Git remote: %s\n", resp.Msg.GitRemoteUrl)
|
||||||
|
|
||||||
|
if _, err := os.Stat(".git"); err == nil {
|
||||||
|
_ = runCmd("git", "remote", "remove", "ninja")
|
||||||
|
if err := runCmd("git", "remote", "add", "ninja", resp.Msg.GitRemoteUrl); err != nil {
|
||||||
|
return fmt.Errorf("git remote add: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Println("Added git remote 'ninja'")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Not in a git repo - skipped adding remote")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := upsertPluginMod(scope, name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("plugin.mod updated")
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmd.Flags().StringVar(&scope, "scope", "", "Scope slug (with or without @)")
|
||||||
|
cmd.Flags().StringVar(&name, "name", "", "Plugin name")
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPluginPublishCmd() *cobra.Command {
|
||||||
|
var channel string
|
||||||
|
var allowDirty bool
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "publish",
|
||||||
|
Short: "Push the current commit as a new version and notify the registry",
|
||||||
|
RunE: func(c *cobra.Command, _ []string) error {
|
||||||
|
host, _ := c.Flags().GetString("host")
|
||||||
|
cr, err := creds.Load()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resolvedHost, hc, err := cr.Resolve(host)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cli := orchclient.New(resolvedHost, hc.Token)
|
||||||
|
|
||||||
|
modBytes, err := os.ReadFile("plugin.mod")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read plugin.mod: %w", err)
|
||||||
|
}
|
||||||
|
mod, err := core.ParseModFull(modBytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if mod.Plugin.Scope == "" || mod.Plugin.Name == "" || mod.Plugin.Version == "" {
|
||||||
|
return fmt.Errorf("plugin.mod must have scope, name, and version")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !allowDirty {
|
||||||
|
out, _ := exec.Command("git", "status", "--porcelain").Output()
|
||||||
|
if len(strings.TrimSpace(string(out))) > 0 {
|
||||||
|
return fmt.Errorf("working tree dirty; commit or pass --allow-dirty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag := "v" + mod.Plugin.Version
|
||||||
|
if err := runCmd("git", "tag", "-a", tag, "-m", tag); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "tag %s already exists or could not be created (%v); attempting push\n", tag, err)
|
||||||
|
}
|
||||||
|
if err := runCmd("git", "push", "ninja", tag); err != nil {
|
||||||
|
return fmt.Errorf("git push ninja %s: %w", tag, err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Pushed %s to ninja remote\n", tag)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
pr, err := cli.Reg.GetPlugin(ctx, connect.NewRequest(&v1.GetPluginRequest{
|
||||||
|
ScopeSlug: mod.Plugin.Scope, Name: mod.Plugin.Name,
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("get plugin: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
readme, _ := os.ReadFile("README.md")
|
||||||
|
changelog, _ := os.ReadFile("CHANGELOG.md")
|
||||||
|
|
||||||
|
pubResp, err := cli.Pub.PublishVersion(ctx, connect.NewRequest(&v1.PublishVersionRequest{
|
||||||
|
PluginId: pr.Msg.Plugin.Id,
|
||||||
|
GitRef: "refs/tags/" + tag,
|
||||||
|
Channel: channel,
|
||||||
|
ReadmeMd: string(readme),
|
||||||
|
ChangelogMd: string(changelog),
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("publish: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Published version_id=%s\n", pubResp.Msg.Version.Id)
|
||||||
|
for _, w := range pubResp.Msg.Warnings {
|
||||||
|
fmt.Printf(" warning: %s\n", w)
|
||||||
|
}
|
||||||
|
fmt.Printf(" Archive: %s\n", pubResp.Msg.ArchiveUrl)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmd.Flags().StringVar(&channel, "channel", "latest", "Channel to point at this version")
|
||||||
|
cmd.Flags().BoolVar(&allowDirty, "allow-dirty", false, "Skip clean-working-tree check")
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPluginStatusCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "status",
|
||||||
|
Short: "List owned scopes and their plugins",
|
||||||
|
RunE: func(c *cobra.Command, _ []string) error {
|
||||||
|
host, _ := c.Flags().GetString("host")
|
||||||
|
cr, err := creds.Load()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resolvedHost, hc, err := cr.Resolve(host)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cli := orchclient.New(resolvedHost, hc.Token)
|
||||||
|
ctx := context.Background()
|
||||||
|
scopes, err := cli.Scope.ListMyScopes(ctx, connect.NewRequest(&v1.ListMyScopesRequest{}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(scopes.Msg.Scopes) == 0 {
|
||||||
|
fmt.Println("No scopes yet. Create one in the orchestrator UI or via a CreateScope call.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, s := range scopes.Msg.Scopes {
|
||||||
|
fmt.Printf("@%s - %s\n", s.Slug, s.DisplayName)
|
||||||
|
gs, err := cli.Scope.GetScope(ctx, connect.NewRequest(&v1.GetScopeRequest{Slug: s.Slug}))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(" (error: %v)\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, p := range gs.Msg.Plugins {
|
||||||
|
fmt.Printf(" @%s/%s [%s]\n", s.Slug, p.Name, p.Visibility)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCmd(name string, args ...string) error {
|
||||||
|
c := exec.Command(name, args...)
|
||||||
|
c.Stderr = os.Stderr
|
||||||
|
return c.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func upsertPluginMod(scope, name string) error {
|
||||||
|
const file = "plugin.mod"
|
||||||
|
existing, _ := os.ReadFile(file)
|
||||||
|
mod, _ := core.ParseModFull(existing)
|
||||||
|
if mod == nil {
|
||||||
|
mod = &core.ModFile{}
|
||||||
|
}
|
||||||
|
if mod.Plugin.Version == "" {
|
||||||
|
mod.Plugin.Version = "0.1.0"
|
||||||
|
}
|
||||||
|
mod.Plugin.Scope = scope
|
||||||
|
mod.Plugin.Name = name
|
||||||
|
return writeMod(file, mod)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeMod(path string, m *core.ModFile) error {
|
||||||
|
var b strings.Builder
|
||||||
|
b.WriteString("[plugin]\n")
|
||||||
|
b.WriteString(fmt.Sprintf("name = %q\n", m.Plugin.Name))
|
||||||
|
b.WriteString(fmt.Sprintf("scope = %q\n", m.Plugin.Scope))
|
||||||
|
b.WriteString(fmt.Sprintf("version = %q\n", m.Plugin.Version))
|
||||||
|
if m.Compatibility != nil {
|
||||||
|
b.WriteString("\n[compatibility]\n")
|
||||||
|
b.WriteString(fmt.Sprintf("block_core = %q\n", m.Compatibility.BlockCore))
|
||||||
|
}
|
||||||
|
for _, r := range m.Requires {
|
||||||
|
b.WriteString("\n[[requires]]\n")
|
||||||
|
b.WriteString(fmt.Sprintf("name = %q\n", r.Name))
|
||||||
|
b.WriteString(fmt.Sprintf("version = %q\n", r.Version))
|
||||||
|
}
|
||||||
|
return os.WriteFile(path, []byte(b.String()), 0o644)
|
||||||
|
}
|
||||||
18
cmd/ninja/cmd/root.go
Normal file
18
cmd/ninja/cmd/root.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import "github.com/spf13/cobra"
|
||||||
|
|
||||||
|
func NewRoot() *cobra.Command {
|
||||||
|
root := &cobra.Command{
|
||||||
|
Use: "ninja",
|
||||||
|
Short: "BlockNinja developer CLI",
|
||||||
|
Long: "ninja is the developer-facing CLI for BlockNinja. First subcommand group: plugin.",
|
||||||
|
}
|
||||||
|
root.PersistentFlags().String("host", "", "Orchestrator base URL (default: from credentials or https://my.blockninjacms.com)")
|
||||||
|
root.AddCommand(newVersionCmd())
|
||||||
|
root.AddCommand(newLoginCmd())
|
||||||
|
root.AddCommand(newLogoutCmd())
|
||||||
|
root.AddCommand(newWhoamiCmd())
|
||||||
|
root.AddCommand(newPluginCmd())
|
||||||
|
return root
|
||||||
|
}
|
||||||
19
cmd/ninja/cmd/version.go
Normal file
19
cmd/ninja/cmd/version.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Version = "dev"
|
||||||
|
|
||||||
|
func newVersionCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "version",
|
||||||
|
Short: "Print ninja version",
|
||||||
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
fmt.Println("ninja", Version)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
77
cmd/ninja/internal/creds/creds.go
Normal file
77
cmd/ninja/internal/creds/creds.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package creds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Credentials struct {
|
||||||
|
DefaultHost string `json:"default_host"`
|
||||||
|
Hosts map[string]HostCreds `json:"hosts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HostCreds struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
User string `json:"user,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func filePath() (string, error) {
|
||||||
|
dir, err := os.UserConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.Join(dir, "ninja", "credentials.json"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Load() (*Credentials, error) {
|
||||||
|
p, err := filePath()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b, err := os.ReadFile(p)
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
return &Credentials{Hosts: map[string]HostCreds{}}, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c := &Credentials{Hosts: map[string]HostCreds{}}
|
||||||
|
if err := json.Unmarshal(b, c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Credentials) Save() error {
|
||||||
|
p, err := filePath()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(filepath.Dir(p), 0o700); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b, err := json.MarshalIndent(c, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.WriteFile(p, b, 0o600)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Credentials) Resolve(host string) (string, HostCreds, error) {
|
||||||
|
if host == "" {
|
||||||
|
host = c.DefaultHost
|
||||||
|
}
|
||||||
|
if host == "" {
|
||||||
|
host = "https://my.blockninjacms.com"
|
||||||
|
}
|
||||||
|
if t := os.Getenv("NINJA_TOKEN"); t != "" {
|
||||||
|
return host, HostCreds{Token: t}, nil
|
||||||
|
}
|
||||||
|
hc, ok := c.Hosts[host]
|
||||||
|
if !ok || hc.Token == "" {
|
||||||
|
return host, HostCreds{}, errors.New("not logged in; run `ninja login`")
|
||||||
|
}
|
||||||
|
return host, hc, nil
|
||||||
|
}
|
||||||
42
cmd/ninja/internal/orchclient/client.go
Normal file
42
cmd/ninja/internal/orchclient/client.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package orchclient
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"connectrpc.com/connect"
|
||||||
|
"git.dev.alexdunmow.com/block/core/internal/api/orchestrator/v1/orchestratorv1connect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
Host string
|
||||||
|
Token string
|
||||||
|
Auth orchestratorv1connect.PluginAuthServiceClient
|
||||||
|
Scope orchestratorv1connect.PluginScopeServiceClient
|
||||||
|
Reg orchestratorv1connect.PluginRegistryServiceClient
|
||||||
|
Pub orchestratorv1connect.PluginPublishServiceClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(host, token string) *Client {
|
||||||
|
httpClient := &http.Client{}
|
||||||
|
opts := []connect.ClientOption{
|
||||||
|
connect.WithInterceptors(bearerInterceptor(token)),
|
||||||
|
}
|
||||||
|
c := &Client{Host: host, Token: token}
|
||||||
|
c.Auth = orchestratorv1connect.NewPluginAuthServiceClient(httpClient, host, opts...)
|
||||||
|
c.Scope = orchestratorv1connect.NewPluginScopeServiceClient(httpClient, host, opts...)
|
||||||
|
c.Reg = orchestratorv1connect.NewPluginRegistryServiceClient(httpClient, host, opts...)
|
||||||
|
c.Pub = orchestratorv1connect.NewPluginPublishServiceClient(httpClient, host, opts...)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func bearerInterceptor(token string) connect.Interceptor {
|
||||||
|
return connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc {
|
||||||
|
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
|
||||||
|
if token != "" {
|
||||||
|
req.Header().Set("Authorization", "Bearer "+token)
|
||||||
|
}
|
||||||
|
return next(ctx, req)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
15
cmd/ninja/main.go
Normal file
15
cmd/ninja/main.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.dev.alexdunmow.com/block/core/cmd/ninja/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := cmd.NewRoot().Execute(); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "Error:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
8
go.mod
8
go.mod
@ -3,18 +3,20 @@ module git.dev.alexdunmow.com/block/core
|
|||||||
go 1.26
|
go 1.26
|
||||||
|
|
||||||
require (
|
require (
|
||||||
connectrpc.com/connect v1.19.2
|
connectrpc.com/connect v1.20.0
|
||||||
github.com/BurntSushi/toml v1.6.0
|
github.com/BurntSushi/toml v1.6.0
|
||||||
github.com/a-h/templ v0.3.1001
|
github.com/a-h/templ v0.3.1001
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/jackc/pgx/v5 v5.9.2
|
github.com/jackc/pgx/v5 v5.9.2
|
||||||
|
github.com/spf13/cobra v1.10.2
|
||||||
golang.org/x/mod v0.34.0
|
golang.org/x/mod v0.34.0
|
||||||
|
google.golang.org/protobuf v1.36.11
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/go-cmp v0.7.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.9 // indirect
|
||||||
golang.org/x/text v0.36.0 // indirect
|
golang.org/x/text v0.36.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.9 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
17
go.sum
17
go.sum
@ -1,9 +1,10 @@
|
|||||||
connectrpc.com/connect v1.19.2 h1:McQ83FGdzL+t60peksi0gXC7MQ/iLKgLduAnThbM0mo=
|
connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ=
|
||||||
connectrpc.com/connect v1.19.2/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
|
connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4=
|
||||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
||||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/a-h/templ v0.3.1001 h1:yHDTgexACdJttyiyamcTHXr2QkIeVF1MukLy44EAhMY=
|
github.com/a-h/templ v0.3.1001 h1:yHDTgexACdJttyiyamcTHXr2QkIeVF1MukLy44EAhMY=
|
||||||
github.com/a-h/templ v0.3.1001/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo=
|
github.com/a-h/templ v0.3.1001/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@ -11,6 +12,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
@ -21,19 +24,25 @@ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo
|
|||||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||||
|
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||||
|
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
||||||
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@ -0,0 +1,597 @@
|
|||||||
|
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
|
||||||
|
//
|
||||||
|
// Source: orchestrator/v1/plugin_registry.proto
|
||||||
|
|
||||||
|
package orchestratorv1connect
|
||||||
|
|
||||||
|
import (
|
||||||
|
connect "connectrpc.com/connect"
|
||||||
|
context "context"
|
||||||
|
errors "errors"
|
||||||
|
v1 "git.dev.alexdunmow.com/block/core/internal/api/orchestrator/v1"
|
||||||
|
http "net/http"
|
||||||
|
strings "strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file and the connect package are
|
||||||
|
// compatible. If you get a compiler error that this constant is not defined, this code was
|
||||||
|
// generated with a version of connect newer than the one compiled into your binary. You can fix the
|
||||||
|
// problem by either regenerating this code with an older version of connect or updating the connect
|
||||||
|
// version compiled into your binary.
|
||||||
|
const _ = connect.IsAtLeastVersion1_13_0
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PluginScopeServiceName is the fully-qualified name of the PluginScopeService service.
|
||||||
|
PluginScopeServiceName = "orchestrator.v1.PluginScopeService"
|
||||||
|
// PluginRegistryServiceName is the fully-qualified name of the PluginRegistryService service.
|
||||||
|
PluginRegistryServiceName = "orchestrator.v1.PluginRegistryService"
|
||||||
|
// PluginPublishServiceName is the fully-qualified name of the PluginPublishService service.
|
||||||
|
PluginPublishServiceName = "orchestrator.v1.PluginPublishService"
|
||||||
|
// PluginAuthServiceName is the fully-qualified name of the PluginAuthService service.
|
||||||
|
PluginAuthServiceName = "orchestrator.v1.PluginAuthService"
|
||||||
|
)
|
||||||
|
|
||||||
|
// These constants are the fully-qualified names of the RPCs defined in this package. They're
|
||||||
|
// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
|
||||||
|
//
|
||||||
|
// Note that these are different from the fully-qualified method names used by
|
||||||
|
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
|
||||||
|
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
|
||||||
|
// period.
|
||||||
|
const (
|
||||||
|
// PluginScopeServiceCreateScopeProcedure is the fully-qualified name of the PluginScopeService's
|
||||||
|
// CreateScope RPC.
|
||||||
|
PluginScopeServiceCreateScopeProcedure = "/orchestrator.v1.PluginScopeService/CreateScope"
|
||||||
|
// PluginScopeServiceListMyScopesProcedure is the fully-qualified name of the PluginScopeService's
|
||||||
|
// ListMyScopes RPC.
|
||||||
|
PluginScopeServiceListMyScopesProcedure = "/orchestrator.v1.PluginScopeService/ListMyScopes"
|
||||||
|
// PluginScopeServiceGetScopeProcedure is the fully-qualified name of the PluginScopeService's
|
||||||
|
// GetScope RPC.
|
||||||
|
PluginScopeServiceGetScopeProcedure = "/orchestrator.v1.PluginScopeService/GetScope"
|
||||||
|
// PluginRegistryServiceCreatePluginProcedure is the fully-qualified name of the
|
||||||
|
// PluginRegistryService's CreatePlugin RPC.
|
||||||
|
PluginRegistryServiceCreatePluginProcedure = "/orchestrator.v1.PluginRegistryService/CreatePlugin"
|
||||||
|
// PluginRegistryServiceGetPluginProcedure is the fully-qualified name of the
|
||||||
|
// PluginRegistryService's GetPlugin RPC.
|
||||||
|
PluginRegistryServiceGetPluginProcedure = "/orchestrator.v1.PluginRegistryService/GetPlugin"
|
||||||
|
// PluginRegistryServiceListPluginsProcedure is the fully-qualified name of the
|
||||||
|
// PluginRegistryService's ListPlugins RPC.
|
||||||
|
PluginRegistryServiceListPluginsProcedure = "/orchestrator.v1.PluginRegistryService/ListPlugins"
|
||||||
|
// PluginRegistryServiceGetVersionProcedure is the fully-qualified name of the
|
||||||
|
// PluginRegistryService's GetVersion RPC.
|
||||||
|
PluginRegistryServiceGetVersionProcedure = "/orchestrator.v1.PluginRegistryService/GetVersion"
|
||||||
|
// PluginRegistryServiceResolveInstallProcedure is the fully-qualified name of the
|
||||||
|
// PluginRegistryService's ResolveInstall RPC.
|
||||||
|
PluginRegistryServiceResolveInstallProcedure = "/orchestrator.v1.PluginRegistryService/ResolveInstall"
|
||||||
|
// PluginPublishServicePublishVersionProcedure is the fully-qualified name of the
|
||||||
|
// PluginPublishService's PublishVersion RPC.
|
||||||
|
PluginPublishServicePublishVersionProcedure = "/orchestrator.v1.PluginPublishService/PublishVersion"
|
||||||
|
// PluginAuthServiceStartDeviceProcedure is the fully-qualified name of the PluginAuthService's
|
||||||
|
// StartDevice RPC.
|
||||||
|
PluginAuthServiceStartDeviceProcedure = "/orchestrator.v1.PluginAuthService/StartDevice"
|
||||||
|
// PluginAuthServicePollDeviceProcedure is the fully-qualified name of the PluginAuthService's
|
||||||
|
// PollDevice RPC.
|
||||||
|
PluginAuthServicePollDeviceProcedure = "/orchestrator.v1.PluginAuthService/PollDevice"
|
||||||
|
// PluginAuthServiceApproveDeviceProcedure is the fully-qualified name of the PluginAuthService's
|
||||||
|
// ApproveDevice RPC.
|
||||||
|
PluginAuthServiceApproveDeviceProcedure = "/orchestrator.v1.PluginAuthService/ApproveDevice"
|
||||||
|
// PluginAuthServiceWhoamiProcedure is the fully-qualified name of the PluginAuthService's Whoami
|
||||||
|
// RPC.
|
||||||
|
PluginAuthServiceWhoamiProcedure = "/orchestrator.v1.PluginAuthService/Whoami"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PluginScopeServiceClient is a client for the orchestrator.v1.PluginScopeService service.
|
||||||
|
type PluginScopeServiceClient interface {
|
||||||
|
CreateScope(context.Context, *connect.Request[v1.CreateScopeRequest]) (*connect.Response[v1.CreateScopeResponse], error)
|
||||||
|
ListMyScopes(context.Context, *connect.Request[v1.ListMyScopesRequest]) (*connect.Response[v1.ListMyScopesResponse], error)
|
||||||
|
GetScope(context.Context, *connect.Request[v1.GetScopeRequest]) (*connect.Response[v1.GetScopeResponse], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPluginScopeServiceClient constructs a client for the orchestrator.v1.PluginScopeService
|
||||||
|
// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for
|
||||||
|
// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply
|
||||||
|
// the connect.WithGRPC() or connect.WithGRPCWeb() options.
|
||||||
|
//
|
||||||
|
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
|
||||||
|
// http://api.acme.com or https://acme.com/grpc).
|
||||||
|
func NewPluginScopeServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) PluginScopeServiceClient {
|
||||||
|
baseURL = strings.TrimRight(baseURL, "/")
|
||||||
|
pluginScopeServiceMethods := v1.File_orchestrator_v1_plugin_registry_proto.Services().ByName("PluginScopeService").Methods()
|
||||||
|
return &pluginScopeServiceClient{
|
||||||
|
createScope: connect.NewClient[v1.CreateScopeRequest, v1.CreateScopeResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginScopeServiceCreateScopeProcedure,
|
||||||
|
connect.WithSchema(pluginScopeServiceMethods.ByName("CreateScope")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
listMyScopes: connect.NewClient[v1.ListMyScopesRequest, v1.ListMyScopesResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginScopeServiceListMyScopesProcedure,
|
||||||
|
connect.WithSchema(pluginScopeServiceMethods.ByName("ListMyScopes")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
getScope: connect.NewClient[v1.GetScopeRequest, v1.GetScopeResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginScopeServiceGetScopeProcedure,
|
||||||
|
connect.WithSchema(pluginScopeServiceMethods.ByName("GetScope")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pluginScopeServiceClient implements PluginScopeServiceClient.
|
||||||
|
type pluginScopeServiceClient struct {
|
||||||
|
createScope *connect.Client[v1.CreateScopeRequest, v1.CreateScopeResponse]
|
||||||
|
listMyScopes *connect.Client[v1.ListMyScopesRequest, v1.ListMyScopesResponse]
|
||||||
|
getScope *connect.Client[v1.GetScopeRequest, v1.GetScopeResponse]
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateScope calls orchestrator.v1.PluginScopeService.CreateScope.
|
||||||
|
func (c *pluginScopeServiceClient) CreateScope(ctx context.Context, req *connect.Request[v1.CreateScopeRequest]) (*connect.Response[v1.CreateScopeResponse], error) {
|
||||||
|
return c.createScope.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyScopes calls orchestrator.v1.PluginScopeService.ListMyScopes.
|
||||||
|
func (c *pluginScopeServiceClient) ListMyScopes(ctx context.Context, req *connect.Request[v1.ListMyScopesRequest]) (*connect.Response[v1.ListMyScopesResponse], error) {
|
||||||
|
return c.listMyScopes.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetScope calls orchestrator.v1.PluginScopeService.GetScope.
|
||||||
|
func (c *pluginScopeServiceClient) GetScope(ctx context.Context, req *connect.Request[v1.GetScopeRequest]) (*connect.Response[v1.GetScopeResponse], error) {
|
||||||
|
return c.getScope.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginScopeServiceHandler is an implementation of the orchestrator.v1.PluginScopeService service.
|
||||||
|
type PluginScopeServiceHandler interface {
|
||||||
|
CreateScope(context.Context, *connect.Request[v1.CreateScopeRequest]) (*connect.Response[v1.CreateScopeResponse], error)
|
||||||
|
ListMyScopes(context.Context, *connect.Request[v1.ListMyScopesRequest]) (*connect.Response[v1.ListMyScopesResponse], error)
|
||||||
|
GetScope(context.Context, *connect.Request[v1.GetScopeRequest]) (*connect.Response[v1.GetScopeResponse], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPluginScopeServiceHandler builds an HTTP handler from the service implementation. It returns
|
||||||
|
// the path on which to mount the handler and the handler itself.
|
||||||
|
//
|
||||||
|
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
|
||||||
|
// and JSON codecs. They also support gzip compression.
|
||||||
|
func NewPluginScopeServiceHandler(svc PluginScopeServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
|
||||||
|
pluginScopeServiceMethods := v1.File_orchestrator_v1_plugin_registry_proto.Services().ByName("PluginScopeService").Methods()
|
||||||
|
pluginScopeServiceCreateScopeHandler := connect.NewUnaryHandler(
|
||||||
|
PluginScopeServiceCreateScopeProcedure,
|
||||||
|
svc.CreateScope,
|
||||||
|
connect.WithSchema(pluginScopeServiceMethods.ByName("CreateScope")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginScopeServiceListMyScopesHandler := connect.NewUnaryHandler(
|
||||||
|
PluginScopeServiceListMyScopesProcedure,
|
||||||
|
svc.ListMyScopes,
|
||||||
|
connect.WithSchema(pluginScopeServiceMethods.ByName("ListMyScopes")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginScopeServiceGetScopeHandler := connect.NewUnaryHandler(
|
||||||
|
PluginScopeServiceGetScopeProcedure,
|
||||||
|
svc.GetScope,
|
||||||
|
connect.WithSchema(pluginScopeServiceMethods.ByName("GetScope")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
return "/orchestrator.v1.PluginScopeService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.URL.Path {
|
||||||
|
case PluginScopeServiceCreateScopeProcedure:
|
||||||
|
pluginScopeServiceCreateScopeHandler.ServeHTTP(w, r)
|
||||||
|
case PluginScopeServiceListMyScopesProcedure:
|
||||||
|
pluginScopeServiceListMyScopesHandler.ServeHTTP(w, r)
|
||||||
|
case PluginScopeServiceGetScopeProcedure:
|
||||||
|
pluginScopeServiceGetScopeHandler.ServeHTTP(w, r)
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedPluginScopeServiceHandler returns CodeUnimplemented from all methods.
|
||||||
|
type UnimplementedPluginScopeServiceHandler struct{}
|
||||||
|
|
||||||
|
func (UnimplementedPluginScopeServiceHandler) CreateScope(context.Context, *connect.Request[v1.CreateScopeRequest]) (*connect.Response[v1.CreateScopeResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginScopeService.CreateScope is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginScopeServiceHandler) ListMyScopes(context.Context, *connect.Request[v1.ListMyScopesRequest]) (*connect.Response[v1.ListMyScopesResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginScopeService.ListMyScopes is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginScopeServiceHandler) GetScope(context.Context, *connect.Request[v1.GetScopeRequest]) (*connect.Response[v1.GetScopeResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginScopeService.GetScope is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginRegistryServiceClient is a client for the orchestrator.v1.PluginRegistryService service.
|
||||||
|
type PluginRegistryServiceClient interface {
|
||||||
|
CreatePlugin(context.Context, *connect.Request[v1.CreatePluginRequest]) (*connect.Response[v1.CreatePluginResponse], error)
|
||||||
|
GetPlugin(context.Context, *connect.Request[v1.GetPluginRequest]) (*connect.Response[v1.GetPluginResponse], error)
|
||||||
|
ListPlugins(context.Context, *connect.Request[v1.ListPluginsRequest]) (*connect.Response[v1.ListPluginsResponse], error)
|
||||||
|
GetVersion(context.Context, *connect.Request[v1.GetVersionRequest]) (*connect.Response[v1.GetVersionResponse], error)
|
||||||
|
ResolveInstall(context.Context, *connect.Request[v1.ResolveInstallRequest]) (*connect.Response[v1.ResolveInstallResponse], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPluginRegistryServiceClient constructs a client for the orchestrator.v1.PluginRegistryService
|
||||||
|
// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for
|
||||||
|
// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply
|
||||||
|
// the connect.WithGRPC() or connect.WithGRPCWeb() options.
|
||||||
|
//
|
||||||
|
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
|
||||||
|
// http://api.acme.com or https://acme.com/grpc).
|
||||||
|
func NewPluginRegistryServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) PluginRegistryServiceClient {
|
||||||
|
baseURL = strings.TrimRight(baseURL, "/")
|
||||||
|
pluginRegistryServiceMethods := v1.File_orchestrator_v1_plugin_registry_proto.Services().ByName("PluginRegistryService").Methods()
|
||||||
|
return &pluginRegistryServiceClient{
|
||||||
|
createPlugin: connect.NewClient[v1.CreatePluginRequest, v1.CreatePluginResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginRegistryServiceCreatePluginProcedure,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("CreatePlugin")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
getPlugin: connect.NewClient[v1.GetPluginRequest, v1.GetPluginResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginRegistryServiceGetPluginProcedure,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("GetPlugin")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
listPlugins: connect.NewClient[v1.ListPluginsRequest, v1.ListPluginsResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginRegistryServiceListPluginsProcedure,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("ListPlugins")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
getVersion: connect.NewClient[v1.GetVersionRequest, v1.GetVersionResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginRegistryServiceGetVersionProcedure,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("GetVersion")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
resolveInstall: connect.NewClient[v1.ResolveInstallRequest, v1.ResolveInstallResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginRegistryServiceResolveInstallProcedure,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("ResolveInstall")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pluginRegistryServiceClient implements PluginRegistryServiceClient.
|
||||||
|
type pluginRegistryServiceClient struct {
|
||||||
|
createPlugin *connect.Client[v1.CreatePluginRequest, v1.CreatePluginResponse]
|
||||||
|
getPlugin *connect.Client[v1.GetPluginRequest, v1.GetPluginResponse]
|
||||||
|
listPlugins *connect.Client[v1.ListPluginsRequest, v1.ListPluginsResponse]
|
||||||
|
getVersion *connect.Client[v1.GetVersionRequest, v1.GetVersionResponse]
|
||||||
|
resolveInstall *connect.Client[v1.ResolveInstallRequest, v1.ResolveInstallResponse]
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePlugin calls orchestrator.v1.PluginRegistryService.CreatePlugin.
|
||||||
|
func (c *pluginRegistryServiceClient) CreatePlugin(ctx context.Context, req *connect.Request[v1.CreatePluginRequest]) (*connect.Response[v1.CreatePluginResponse], error) {
|
||||||
|
return c.createPlugin.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlugin calls orchestrator.v1.PluginRegistryService.GetPlugin.
|
||||||
|
func (c *pluginRegistryServiceClient) GetPlugin(ctx context.Context, req *connect.Request[v1.GetPluginRequest]) (*connect.Response[v1.GetPluginResponse], error) {
|
||||||
|
return c.getPlugin.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPlugins calls orchestrator.v1.PluginRegistryService.ListPlugins.
|
||||||
|
func (c *pluginRegistryServiceClient) ListPlugins(ctx context.Context, req *connect.Request[v1.ListPluginsRequest]) (*connect.Response[v1.ListPluginsResponse], error) {
|
||||||
|
return c.listPlugins.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVersion calls orchestrator.v1.PluginRegistryService.GetVersion.
|
||||||
|
func (c *pluginRegistryServiceClient) GetVersion(ctx context.Context, req *connect.Request[v1.GetVersionRequest]) (*connect.Response[v1.GetVersionResponse], error) {
|
||||||
|
return c.getVersion.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveInstall calls orchestrator.v1.PluginRegistryService.ResolveInstall.
|
||||||
|
func (c *pluginRegistryServiceClient) ResolveInstall(ctx context.Context, req *connect.Request[v1.ResolveInstallRequest]) (*connect.Response[v1.ResolveInstallResponse], error) {
|
||||||
|
return c.resolveInstall.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginRegistryServiceHandler is an implementation of the orchestrator.v1.PluginRegistryService
|
||||||
|
// service.
|
||||||
|
type PluginRegistryServiceHandler interface {
|
||||||
|
CreatePlugin(context.Context, *connect.Request[v1.CreatePluginRequest]) (*connect.Response[v1.CreatePluginResponse], error)
|
||||||
|
GetPlugin(context.Context, *connect.Request[v1.GetPluginRequest]) (*connect.Response[v1.GetPluginResponse], error)
|
||||||
|
ListPlugins(context.Context, *connect.Request[v1.ListPluginsRequest]) (*connect.Response[v1.ListPluginsResponse], error)
|
||||||
|
GetVersion(context.Context, *connect.Request[v1.GetVersionRequest]) (*connect.Response[v1.GetVersionResponse], error)
|
||||||
|
ResolveInstall(context.Context, *connect.Request[v1.ResolveInstallRequest]) (*connect.Response[v1.ResolveInstallResponse], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPluginRegistryServiceHandler builds an HTTP handler from the service implementation. It
|
||||||
|
// returns the path on which to mount the handler and the handler itself.
|
||||||
|
//
|
||||||
|
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
|
||||||
|
// and JSON codecs. They also support gzip compression.
|
||||||
|
func NewPluginRegistryServiceHandler(svc PluginRegistryServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
|
||||||
|
pluginRegistryServiceMethods := v1.File_orchestrator_v1_plugin_registry_proto.Services().ByName("PluginRegistryService").Methods()
|
||||||
|
pluginRegistryServiceCreatePluginHandler := connect.NewUnaryHandler(
|
||||||
|
PluginRegistryServiceCreatePluginProcedure,
|
||||||
|
svc.CreatePlugin,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("CreatePlugin")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginRegistryServiceGetPluginHandler := connect.NewUnaryHandler(
|
||||||
|
PluginRegistryServiceGetPluginProcedure,
|
||||||
|
svc.GetPlugin,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("GetPlugin")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginRegistryServiceListPluginsHandler := connect.NewUnaryHandler(
|
||||||
|
PluginRegistryServiceListPluginsProcedure,
|
||||||
|
svc.ListPlugins,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("ListPlugins")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginRegistryServiceGetVersionHandler := connect.NewUnaryHandler(
|
||||||
|
PluginRegistryServiceGetVersionProcedure,
|
||||||
|
svc.GetVersion,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("GetVersion")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginRegistryServiceResolveInstallHandler := connect.NewUnaryHandler(
|
||||||
|
PluginRegistryServiceResolveInstallProcedure,
|
||||||
|
svc.ResolveInstall,
|
||||||
|
connect.WithSchema(pluginRegistryServiceMethods.ByName("ResolveInstall")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
return "/orchestrator.v1.PluginRegistryService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.URL.Path {
|
||||||
|
case PluginRegistryServiceCreatePluginProcedure:
|
||||||
|
pluginRegistryServiceCreatePluginHandler.ServeHTTP(w, r)
|
||||||
|
case PluginRegistryServiceGetPluginProcedure:
|
||||||
|
pluginRegistryServiceGetPluginHandler.ServeHTTP(w, r)
|
||||||
|
case PluginRegistryServiceListPluginsProcedure:
|
||||||
|
pluginRegistryServiceListPluginsHandler.ServeHTTP(w, r)
|
||||||
|
case PluginRegistryServiceGetVersionProcedure:
|
||||||
|
pluginRegistryServiceGetVersionHandler.ServeHTTP(w, r)
|
||||||
|
case PluginRegistryServiceResolveInstallProcedure:
|
||||||
|
pluginRegistryServiceResolveInstallHandler.ServeHTTP(w, r)
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedPluginRegistryServiceHandler returns CodeUnimplemented from all methods.
|
||||||
|
type UnimplementedPluginRegistryServiceHandler struct{}
|
||||||
|
|
||||||
|
func (UnimplementedPluginRegistryServiceHandler) CreatePlugin(context.Context, *connect.Request[v1.CreatePluginRequest]) (*connect.Response[v1.CreatePluginResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginRegistryService.CreatePlugin is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginRegistryServiceHandler) GetPlugin(context.Context, *connect.Request[v1.GetPluginRequest]) (*connect.Response[v1.GetPluginResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginRegistryService.GetPlugin is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginRegistryServiceHandler) ListPlugins(context.Context, *connect.Request[v1.ListPluginsRequest]) (*connect.Response[v1.ListPluginsResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginRegistryService.ListPlugins is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginRegistryServiceHandler) GetVersion(context.Context, *connect.Request[v1.GetVersionRequest]) (*connect.Response[v1.GetVersionResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginRegistryService.GetVersion is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginRegistryServiceHandler) ResolveInstall(context.Context, *connect.Request[v1.ResolveInstallRequest]) (*connect.Response[v1.ResolveInstallResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginRegistryService.ResolveInstall is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginPublishServiceClient is a client for the orchestrator.v1.PluginPublishService service.
|
||||||
|
type PluginPublishServiceClient interface {
|
||||||
|
PublishVersion(context.Context, *connect.Request[v1.PublishVersionRequest]) (*connect.Response[v1.PublishVersionResponse], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPluginPublishServiceClient constructs a client for the orchestrator.v1.PluginPublishService
|
||||||
|
// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for
|
||||||
|
// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply
|
||||||
|
// the connect.WithGRPC() or connect.WithGRPCWeb() options.
|
||||||
|
//
|
||||||
|
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
|
||||||
|
// http://api.acme.com or https://acme.com/grpc).
|
||||||
|
func NewPluginPublishServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) PluginPublishServiceClient {
|
||||||
|
baseURL = strings.TrimRight(baseURL, "/")
|
||||||
|
pluginPublishServiceMethods := v1.File_orchestrator_v1_plugin_registry_proto.Services().ByName("PluginPublishService").Methods()
|
||||||
|
return &pluginPublishServiceClient{
|
||||||
|
publishVersion: connect.NewClient[v1.PublishVersionRequest, v1.PublishVersionResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginPublishServicePublishVersionProcedure,
|
||||||
|
connect.WithSchema(pluginPublishServiceMethods.ByName("PublishVersion")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pluginPublishServiceClient implements PluginPublishServiceClient.
|
||||||
|
type pluginPublishServiceClient struct {
|
||||||
|
publishVersion *connect.Client[v1.PublishVersionRequest, v1.PublishVersionResponse]
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublishVersion calls orchestrator.v1.PluginPublishService.PublishVersion.
|
||||||
|
func (c *pluginPublishServiceClient) PublishVersion(ctx context.Context, req *connect.Request[v1.PublishVersionRequest]) (*connect.Response[v1.PublishVersionResponse], error) {
|
||||||
|
return c.publishVersion.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginPublishServiceHandler is an implementation of the orchestrator.v1.PluginPublishService
|
||||||
|
// service.
|
||||||
|
type PluginPublishServiceHandler interface {
|
||||||
|
PublishVersion(context.Context, *connect.Request[v1.PublishVersionRequest]) (*connect.Response[v1.PublishVersionResponse], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPluginPublishServiceHandler builds an HTTP handler from the service implementation. It returns
|
||||||
|
// the path on which to mount the handler and the handler itself.
|
||||||
|
//
|
||||||
|
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
|
||||||
|
// and JSON codecs. They also support gzip compression.
|
||||||
|
func NewPluginPublishServiceHandler(svc PluginPublishServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
|
||||||
|
pluginPublishServiceMethods := v1.File_orchestrator_v1_plugin_registry_proto.Services().ByName("PluginPublishService").Methods()
|
||||||
|
pluginPublishServicePublishVersionHandler := connect.NewUnaryHandler(
|
||||||
|
PluginPublishServicePublishVersionProcedure,
|
||||||
|
svc.PublishVersion,
|
||||||
|
connect.WithSchema(pluginPublishServiceMethods.ByName("PublishVersion")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
return "/orchestrator.v1.PluginPublishService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.URL.Path {
|
||||||
|
case PluginPublishServicePublishVersionProcedure:
|
||||||
|
pluginPublishServicePublishVersionHandler.ServeHTTP(w, r)
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedPluginPublishServiceHandler returns CodeUnimplemented from all methods.
|
||||||
|
type UnimplementedPluginPublishServiceHandler struct{}
|
||||||
|
|
||||||
|
func (UnimplementedPluginPublishServiceHandler) PublishVersion(context.Context, *connect.Request[v1.PublishVersionRequest]) (*connect.Response[v1.PublishVersionResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginPublishService.PublishVersion is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginAuthServiceClient is a client for the orchestrator.v1.PluginAuthService service.
|
||||||
|
type PluginAuthServiceClient interface {
|
||||||
|
StartDevice(context.Context, *connect.Request[v1.StartDeviceRequest]) (*connect.Response[v1.StartDeviceResponse], error)
|
||||||
|
PollDevice(context.Context, *connect.Request[v1.PollDeviceRequest]) (*connect.Response[v1.PollDeviceResponse], error)
|
||||||
|
ApproveDevice(context.Context, *connect.Request[v1.ApproveDeviceRequest]) (*connect.Response[v1.ApproveDeviceResponse], error)
|
||||||
|
Whoami(context.Context, *connect.Request[v1.WhoamiRequest]) (*connect.Response[v1.WhoamiResponse], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPluginAuthServiceClient constructs a client for the orchestrator.v1.PluginAuthService service.
|
||||||
|
// By default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped
|
||||||
|
// responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
|
||||||
|
// connect.WithGRPC() or connect.WithGRPCWeb() options.
|
||||||
|
//
|
||||||
|
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
|
||||||
|
// http://api.acme.com or https://acme.com/grpc).
|
||||||
|
func NewPluginAuthServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) PluginAuthServiceClient {
|
||||||
|
baseURL = strings.TrimRight(baseURL, "/")
|
||||||
|
pluginAuthServiceMethods := v1.File_orchestrator_v1_plugin_registry_proto.Services().ByName("PluginAuthService").Methods()
|
||||||
|
return &pluginAuthServiceClient{
|
||||||
|
startDevice: connect.NewClient[v1.StartDeviceRequest, v1.StartDeviceResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginAuthServiceStartDeviceProcedure,
|
||||||
|
connect.WithSchema(pluginAuthServiceMethods.ByName("StartDevice")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
pollDevice: connect.NewClient[v1.PollDeviceRequest, v1.PollDeviceResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginAuthServicePollDeviceProcedure,
|
||||||
|
connect.WithSchema(pluginAuthServiceMethods.ByName("PollDevice")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
approveDevice: connect.NewClient[v1.ApproveDeviceRequest, v1.ApproveDeviceResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginAuthServiceApproveDeviceProcedure,
|
||||||
|
connect.WithSchema(pluginAuthServiceMethods.ByName("ApproveDevice")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
whoami: connect.NewClient[v1.WhoamiRequest, v1.WhoamiResponse](
|
||||||
|
httpClient,
|
||||||
|
baseURL+PluginAuthServiceWhoamiProcedure,
|
||||||
|
connect.WithSchema(pluginAuthServiceMethods.ByName("Whoami")),
|
||||||
|
connect.WithClientOptions(opts...),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pluginAuthServiceClient implements PluginAuthServiceClient.
|
||||||
|
type pluginAuthServiceClient struct {
|
||||||
|
startDevice *connect.Client[v1.StartDeviceRequest, v1.StartDeviceResponse]
|
||||||
|
pollDevice *connect.Client[v1.PollDeviceRequest, v1.PollDeviceResponse]
|
||||||
|
approveDevice *connect.Client[v1.ApproveDeviceRequest, v1.ApproveDeviceResponse]
|
||||||
|
whoami *connect.Client[v1.WhoamiRequest, v1.WhoamiResponse]
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartDevice calls orchestrator.v1.PluginAuthService.StartDevice.
|
||||||
|
func (c *pluginAuthServiceClient) StartDevice(ctx context.Context, req *connect.Request[v1.StartDeviceRequest]) (*connect.Response[v1.StartDeviceResponse], error) {
|
||||||
|
return c.startDevice.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PollDevice calls orchestrator.v1.PluginAuthService.PollDevice.
|
||||||
|
func (c *pluginAuthServiceClient) PollDevice(ctx context.Context, req *connect.Request[v1.PollDeviceRequest]) (*connect.Response[v1.PollDeviceResponse], error) {
|
||||||
|
return c.pollDevice.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApproveDevice calls orchestrator.v1.PluginAuthService.ApproveDevice.
|
||||||
|
func (c *pluginAuthServiceClient) ApproveDevice(ctx context.Context, req *connect.Request[v1.ApproveDeviceRequest]) (*connect.Response[v1.ApproveDeviceResponse], error) {
|
||||||
|
return c.approveDevice.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whoami calls orchestrator.v1.PluginAuthService.Whoami.
|
||||||
|
func (c *pluginAuthServiceClient) Whoami(ctx context.Context, req *connect.Request[v1.WhoamiRequest]) (*connect.Response[v1.WhoamiResponse], error) {
|
||||||
|
return c.whoami.CallUnary(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginAuthServiceHandler is an implementation of the orchestrator.v1.PluginAuthService service.
|
||||||
|
type PluginAuthServiceHandler interface {
|
||||||
|
StartDevice(context.Context, *connect.Request[v1.StartDeviceRequest]) (*connect.Response[v1.StartDeviceResponse], error)
|
||||||
|
PollDevice(context.Context, *connect.Request[v1.PollDeviceRequest]) (*connect.Response[v1.PollDeviceResponse], error)
|
||||||
|
ApproveDevice(context.Context, *connect.Request[v1.ApproveDeviceRequest]) (*connect.Response[v1.ApproveDeviceResponse], error)
|
||||||
|
Whoami(context.Context, *connect.Request[v1.WhoamiRequest]) (*connect.Response[v1.WhoamiResponse], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPluginAuthServiceHandler builds an HTTP handler from the service implementation. It returns
|
||||||
|
// the path on which to mount the handler and the handler itself.
|
||||||
|
//
|
||||||
|
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
|
||||||
|
// and JSON codecs. They also support gzip compression.
|
||||||
|
func NewPluginAuthServiceHandler(svc PluginAuthServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
|
||||||
|
pluginAuthServiceMethods := v1.File_orchestrator_v1_plugin_registry_proto.Services().ByName("PluginAuthService").Methods()
|
||||||
|
pluginAuthServiceStartDeviceHandler := connect.NewUnaryHandler(
|
||||||
|
PluginAuthServiceStartDeviceProcedure,
|
||||||
|
svc.StartDevice,
|
||||||
|
connect.WithSchema(pluginAuthServiceMethods.ByName("StartDevice")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginAuthServicePollDeviceHandler := connect.NewUnaryHandler(
|
||||||
|
PluginAuthServicePollDeviceProcedure,
|
||||||
|
svc.PollDevice,
|
||||||
|
connect.WithSchema(pluginAuthServiceMethods.ByName("PollDevice")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginAuthServiceApproveDeviceHandler := connect.NewUnaryHandler(
|
||||||
|
PluginAuthServiceApproveDeviceProcedure,
|
||||||
|
svc.ApproveDevice,
|
||||||
|
connect.WithSchema(pluginAuthServiceMethods.ByName("ApproveDevice")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
pluginAuthServiceWhoamiHandler := connect.NewUnaryHandler(
|
||||||
|
PluginAuthServiceWhoamiProcedure,
|
||||||
|
svc.Whoami,
|
||||||
|
connect.WithSchema(pluginAuthServiceMethods.ByName("Whoami")),
|
||||||
|
connect.WithHandlerOptions(opts...),
|
||||||
|
)
|
||||||
|
return "/orchestrator.v1.PluginAuthService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.URL.Path {
|
||||||
|
case PluginAuthServiceStartDeviceProcedure:
|
||||||
|
pluginAuthServiceStartDeviceHandler.ServeHTTP(w, r)
|
||||||
|
case PluginAuthServicePollDeviceProcedure:
|
||||||
|
pluginAuthServicePollDeviceHandler.ServeHTTP(w, r)
|
||||||
|
case PluginAuthServiceApproveDeviceProcedure:
|
||||||
|
pluginAuthServiceApproveDeviceHandler.ServeHTTP(w, r)
|
||||||
|
case PluginAuthServiceWhoamiProcedure:
|
||||||
|
pluginAuthServiceWhoamiHandler.ServeHTTP(w, r)
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedPluginAuthServiceHandler returns CodeUnimplemented from all methods.
|
||||||
|
type UnimplementedPluginAuthServiceHandler struct{}
|
||||||
|
|
||||||
|
func (UnimplementedPluginAuthServiceHandler) StartDevice(context.Context, *connect.Request[v1.StartDeviceRequest]) (*connect.Response[v1.StartDeviceResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginAuthService.StartDevice is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginAuthServiceHandler) PollDevice(context.Context, *connect.Request[v1.PollDeviceRequest]) (*connect.Response[v1.PollDeviceResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginAuthService.PollDevice is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginAuthServiceHandler) ApproveDevice(context.Context, *connect.Request[v1.ApproveDeviceRequest]) (*connect.Response[v1.ApproveDeviceResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginAuthService.ApproveDevice is not implemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedPluginAuthServiceHandler) Whoami(context.Context, *connect.Request[v1.WhoamiRequest]) (*connect.Response[v1.WhoamiResponse], error) {
|
||||||
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginAuthService.Whoami is not implemented"))
|
||||||
|
}
|
||||||
2108
internal/api/orchestrator/v1/plugin_registry.pb.go
Normal file
2108
internal/api/orchestrator/v1/plugin_registry.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
184
proto/orchestrator/v1/plugin_registry.proto
Normal file
184
proto/orchestrator/v1/plugin_registry.proto
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package orchestrator.v1;
|
||||||
|
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
|
option go_package = "git.dev.alexdunmow.com/block/ninja/orchestrator/internal/api/orchestrator/v1;orchestratorv1";
|
||||||
|
|
||||||
|
// PluginScopeService manages @scope namespaces.
|
||||||
|
service PluginScopeService {
|
||||||
|
rpc CreateScope(CreateScopeRequest) returns (CreateScopeResponse);
|
||||||
|
rpc ListMyScopes(ListMyScopesRequest) returns (ListMyScopesResponse);
|
||||||
|
rpc GetScope(GetScopeRequest) returns (GetScopeResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginRegistryService is the read-side public API plus CreatePlugin.
|
||||||
|
service PluginRegistryService {
|
||||||
|
rpc CreatePlugin(CreatePluginRequest) returns (CreatePluginResponse);
|
||||||
|
rpc GetPlugin(GetPluginRequest) returns (GetPluginResponse);
|
||||||
|
rpc ListPlugins(ListPluginsRequest) returns (ListPluginsResponse);
|
||||||
|
rpc GetVersion(GetVersionRequest) returns (GetVersionResponse);
|
||||||
|
rpc ResolveInstall(ResolveInstallRequest) returns (ResolveInstallResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginPublishService is called by the ninja CLI to publish a version.
|
||||||
|
service PluginPublishService {
|
||||||
|
rpc PublishVersion(PublishVersionRequest) returns (PublishVersionResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginAuthService handles OAuth device flow used by ninja CLI.
|
||||||
|
service PluginAuthService {
|
||||||
|
rpc StartDevice(StartDeviceRequest) returns (StartDeviceResponse);
|
||||||
|
rpc PollDevice(PollDeviceRequest) returns (PollDeviceResponse);
|
||||||
|
rpc ApproveDevice(ApproveDeviceRequest) returns (ApproveDeviceResponse);
|
||||||
|
rpc Whoami(WhoamiRequest) returns (WhoamiResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Shared messages ---
|
||||||
|
|
||||||
|
message Scope {
|
||||||
|
string id = 1;
|
||||||
|
string slug = 2;
|
||||||
|
string display_name = 3;
|
||||||
|
google.protobuf.Timestamp created_at = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Plugin {
|
||||||
|
string id = 1;
|
||||||
|
string scope_slug = 2;
|
||||||
|
string name = 3;
|
||||||
|
string visibility = 4;
|
||||||
|
bool premium = 5;
|
||||||
|
string description = 6;
|
||||||
|
string homepage_url = 7;
|
||||||
|
repeated string categories = 8;
|
||||||
|
google.protobuf.Timestamp updated_at = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Version {
|
||||||
|
string id = 1;
|
||||||
|
string plugin_id = 2;
|
||||||
|
string version = 3;
|
||||||
|
string git_commit = 4;
|
||||||
|
string git_tag = 5;
|
||||||
|
google.protobuf.Timestamp published_at = 6;
|
||||||
|
bool yanked = 7;
|
||||||
|
string sdk_constraint = 8;
|
||||||
|
string source_archive_sha256 = 9;
|
||||||
|
int64 source_archive_size = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Requirement {
|
||||||
|
string scope_slug = 1;
|
||||||
|
string name = 2;
|
||||||
|
string constraint_expr = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Scope service ---
|
||||||
|
|
||||||
|
message CreateScopeRequest { string slug = 1; string display_name = 2; }
|
||||||
|
message CreateScopeResponse { Scope scope = 1; }
|
||||||
|
message ListMyScopesRequest {}
|
||||||
|
message ListMyScopesResponse { repeated Scope scopes = 1; }
|
||||||
|
message GetScopeRequest { string slug = 1; }
|
||||||
|
message GetScopeResponse { Scope scope = 1; repeated Plugin plugins = 2; }
|
||||||
|
|
||||||
|
// --- Registry service ---
|
||||||
|
|
||||||
|
message CreatePluginRequest {
|
||||||
|
string scope_slug = 1;
|
||||||
|
string name = 2;
|
||||||
|
string description = 3;
|
||||||
|
}
|
||||||
|
message CreatePluginResponse {
|
||||||
|
Plugin plugin = 1;
|
||||||
|
string git_remote_url = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetPluginRequest { string scope_slug = 1; string name = 2; }
|
||||||
|
message GetPluginResponse {
|
||||||
|
Plugin plugin = 1;
|
||||||
|
repeated Version versions = 2;
|
||||||
|
map<string,string> channels = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListPluginsRequest {
|
||||||
|
int32 limit = 1;
|
||||||
|
int32 offset = 2;
|
||||||
|
string query = 3;
|
||||||
|
}
|
||||||
|
message ListPluginsResponse { repeated Plugin plugins = 1; }
|
||||||
|
|
||||||
|
message GetVersionRequest {
|
||||||
|
string scope_slug = 1;
|
||||||
|
string plugin_name = 2;
|
||||||
|
string version = 3;
|
||||||
|
}
|
||||||
|
message GetVersionResponse {
|
||||||
|
Version version = 1;
|
||||||
|
repeated Requirement requires = 2;
|
||||||
|
string readme_md = 3;
|
||||||
|
string changelog_md = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResolveInstallRequest {
|
||||||
|
string scope_slug = 1;
|
||||||
|
string plugin_name = 2;
|
||||||
|
string version_or_channel = 3;
|
||||||
|
}
|
||||||
|
message ResolveInstallResponse {
|
||||||
|
string version_id = 1;
|
||||||
|
string scope_slug = 2;
|
||||||
|
string plugin_name = 3;
|
||||||
|
string version = 4;
|
||||||
|
string channel_pinned = 5;
|
||||||
|
string archive_url = 6;
|
||||||
|
string archive_sha256 = 7;
|
||||||
|
string sdk_constraint = 8;
|
||||||
|
repeated Requirement requires = 9;
|
||||||
|
bool yanked = 10;
|
||||||
|
repeated string warnings = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Publish service ---
|
||||||
|
|
||||||
|
message PublishVersionRequest {
|
||||||
|
string plugin_id = 1;
|
||||||
|
string git_ref = 2;
|
||||||
|
string channel = 3;
|
||||||
|
string readme_md = 4;
|
||||||
|
string changelog_md = 5;
|
||||||
|
}
|
||||||
|
message PublishVersionResponse {
|
||||||
|
Version version = 1;
|
||||||
|
string archive_url = 2;
|
||||||
|
repeated string warnings = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Auth service (device flow) ---
|
||||||
|
|
||||||
|
message StartDeviceRequest { repeated string scopes = 1; }
|
||||||
|
message StartDeviceResponse {
|
||||||
|
string device_code = 1;
|
||||||
|
string user_code = 2;
|
||||||
|
string verification_uri = 3;
|
||||||
|
int32 interval_seconds = 4;
|
||||||
|
int32 expires_in_seconds = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PollDeviceRequest { string device_code = 1; }
|
||||||
|
message PollDeviceResponse {
|
||||||
|
string access_token = 1;
|
||||||
|
string status = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ApproveDeviceRequest { string user_code = 1; }
|
||||||
|
message ApproveDeviceResponse {}
|
||||||
|
|
||||||
|
message WhoamiRequest {}
|
||||||
|
message WhoamiResponse {
|
||||||
|
string user_id = 1;
|
||||||
|
string email = 2;
|
||||||
|
string display_name = 3;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user