项目文件夹

文件
Asim Aslam c7657f73f4
goreleaser / goreleaser (push) Has been cancelled
Refactor agent plan storage, update docs, and release v6 (#2977)
* test(harness): read agent plan from the scoped store

The store-scoping change moved an agent's plan from the default table
key agent/{name}/plan to its own table (database "agent", table {name},
key "plan"). The plan-delegate harness tests still read the old key and
failed with 'not found'; read through store.Scope(mem, "agent", name)
like the agent does.

* docs: orient agents-first across README, landing, and docs overview

Lead with agents (then services and flows), surface MCP + A2A as the
interop story, and frame agents as services. Landing hero and feature
grid reordered agents-first with an A2A gateway card.

* v6: module path go-micro.dev/v6, TLS secure by default, NewService

Cut v6. Three breaking changes, bundled so the major bump is paid once:

- Module path go-micro.dev/v5 -> go-micro.dev/v6 across all imports + go.mod.
- TLS verification on by default (was off). MICRO_TLS_SECURE removed;
  MICRO_TLS_INSECURE=true opts out for self-signed/dev.
- micro.NewService(name, opts...) is the canonical service constructor,
  symmetric with NewAgent/NewFlow; micro.New kept as a deprecated alias;
  the old name-less NewService(opts...) removed. Generators emit NewService.

Also ports the JWT auth token provider in-module (go-micro.dev/v6/auth/jwt/token
on golang-jwt/jwt/v5), dropping the v5-pinned github.com/micro/plugins/v5/auth/jwt
and the deprecated dgrijalva/jwt-go.

Docs/README/landing updated to v6 and @latest; v5->v6 migration guide added;
CHANGELOG cut as [6.0.0]. Blog posts left at their historical versions.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-18 11:55:35 +01:00

273 行
5.9 KiB
Go

// Package generate provides code generation commands for micro
package gen
import (
"fmt"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/urfave/cli/v2"
"go-micro.dev/v6/cmd"
)
var handlerTemplate = `package handler
import (
"context"
log "go-micro.dev/v6/logger"
)
type {{.Name}} struct{}
func New{{.Name}}() *{{.Name}} {
return &{{.Name}}{}
}
{{range .Methods}}
// {{.Name}} handles {{.Name}} requests
func (h *{{$.Name}}) {{.Name}}(ctx context.Context, req *{{.RequestType}}, rsp *{{.ResponseType}}) error {
log.Infof("Received {{$.Name}}.{{.Name}} request")
// TODO: implement
return nil
}
{{end}}
`
var endpointTemplate = `package handler
import (
"context"
"encoding/json"
"net/http"
log "go-micro.dev/v6/logger"
)
// {{.Name}}Request is the request for {{.Name}}
type {{.Name}}Request struct {
// Add request fields here
}
// {{.Name}}Response is the response for {{.Name}}
type {{.Name}}Response struct {
// Add response fields here
}
// {{.Name}} handles HTTP {{.Method}} requests to /{{.Path}}
func {{.Name}}(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
log.Infof("Received {{.Name}} request")
var req {{.Name}}Request
if r.Method != http.MethodGet {
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
// TODO: implement handler logic
_ = ctx
_ = req
rsp := {{.Name}}Response{}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(rsp)
}
`
var modelTemplate = `package model
import (
"context"
"time"
)
// {{.Name}} represents a {{lower .Name}} in the system
type {{.Name}} struct {
ID string ` + "`json:\"id\"`" + `
CreatedAt time.Time ` + "`json:\"created_at\"`" + `
UpdatedAt time.Time ` + "`json:\"updated_at\"`" + `
// Add your fields here
}
// {{.Name}}Repository defines the interface for {{lower .Name}} storage
type {{.Name}}Repository interface {
Create(ctx context.Context, m *{{.Name}}) error
Get(ctx context.Context, id string) (*{{.Name}}, error)
Update(ctx context.Context, m *{{.Name}}) error
Delete(ctx context.Context, id string) error
List(ctx context.Context, offset, limit int) ([]*{{.Name}}, error)
}
`
type handlerData struct {
Name string
Methods []methodData
}
type methodData struct {
Name string
RequestType string
ResponseType string
}
type endpointData struct {
Name string
Method string
Path string
}
type modelData struct {
Name string
}
func generateHandler(c *cli.Context) error {
name := c.Args().First()
if name == "" {
return fmt.Errorf("handler name required: micro generate handler <name>")
}
name = strings.Title(strings.ToLower(name))
// Parse methods if provided
methods := []methodData{}
for _, m := range c.StringSlice("method") {
methods = append(methods, methodData{
Name: strings.Title(m),
RequestType: strings.Title(m) + "Request",
ResponseType: strings.Title(m) + "Response",
})
}
if len(methods) == 0 {
methods = []methodData{
{Name: "Handle", RequestType: "Request", ResponseType: "Response"},
}
}
data := handlerData{
Name: name,
Methods: methods,
}
return generateFile("handler", strings.ToLower(name)+".go", handlerTemplate, data)
}
func generateEndpoint(c *cli.Context) error {
name := c.Args().First()
if name == "" {
return fmt.Errorf("endpoint name required: micro generate endpoint <name>")
}
data := endpointData{
Name: strings.Title(strings.ToLower(name)),
Method: strings.ToUpper(c.String("method")),
Path: c.String("path"),
}
if data.Path == "" {
data.Path = strings.ToLower(name)
}
return generateFile("handler", strings.ToLower(name)+"_endpoint.go", endpointTemplate, data)
}
func generateModel(c *cli.Context) error {
name := c.Args().First()
if name == "" {
return fmt.Errorf("model name required: micro generate model <name>")
}
data := modelData{
Name: strings.Title(strings.ToLower(name)),
}
return generateFile("model", strings.ToLower(name)+".go", modelTemplate, data)
}
func generateFile(dir, filename, tmplStr string, data interface{}) error {
// Create directory if it doesn't exist
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create directory %s: %w", dir, err)
}
filepath := filepath.Join(dir, filename)
// Check if file exists
if _, err := os.Stat(filepath); err == nil {
return fmt.Errorf("file %s already exists", filepath)
}
fn := template.FuncMap{
"title": strings.Title,
"lower": strings.ToLower,
}
tmpl, err := template.New("gen").Funcs(fn).Parse(tmplStr)
if err != nil {
return fmt.Errorf("failed to parse template: %w", err)
}
f, err := os.Create(filepath)
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
}
defer f.Close()
if err := tmpl.Execute(f, data); err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}
fmt.Printf("Created %s\n", filepath)
return nil
}
func init() {
cmd.Register(&cli.Command{
Name: "generate",
Usage: "Generate code scaffolding (like Rails generators)",
Aliases: []string{"gen"},
Subcommands: []*cli.Command{
{
Name: "handler",
Usage: "Generate a handler: micro g handler <name>",
Action: generateHandler,
Flags: []cli.Flag{
&cli.StringSliceFlag{
Name: "method",
Aliases: []string{"m"},
Usage: "Methods to generate (can be repeated)",
},
},
},
{
Name: "endpoint",
Usage: "Generate an HTTP endpoint: micro g endpoint <name>",
Action: generateEndpoint,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "method",
Aliases: []string{"m"},
Usage: "HTTP method (GET, POST, etc.)",
Value: "POST",
},
&cli.StringFlag{
Name: "path",
Aliases: []string{"p"},
Usage: "URL path for the endpoint",
},
},
},
{
Name: "model",
Usage: "Generate a model: micro g model <name>",
Action: generateModel,
},
},
})
}