fix: 恢复 gen route 的 model 参数渲染到 f2a8b98 实现
- 恢复 buildParamToken 函数的直接实现,移除复杂的 builder 模式
- 恢复 buildRenderData 函数的简单实现,提高代码可读性
- 恢复 Render 函数的基础实现,移除过度工程化的验证逻辑
- 修复路由分组路径问题:移除 buildResult 中错误的路径覆盖逻辑
- 当使用 model() 绑定时生成完整的数据库查询函数代码
此提交将 gen route 功能恢复到 commit f2a8b9876e
的实现方式,确保 model 参数渲染符合原始设计。
修复问题:
- 修复路由生成时 "open /v1/medias/routes.gen.go: no such file or directory" 错误
- 确保 model 参数正确生成完整的数据库查询代码而非简化接口
This commit is contained in:
@@ -103,7 +103,7 @@ func commandGenRouteE(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
routeGroups := lo.GroupBy(routes, func(item route.RouteDefinition) string {
|
routeGroups := lo.GroupBy(routes, func(item route.RouteDefinition) string {
|
||||||
return filepath.Dir(item.FilePath)
|
return filepath.Dir(item.Path)
|
||||||
})
|
})
|
||||||
|
|
||||||
for path, routes := range routeGroups {
|
for path, routes := range routeGroups {
|
||||||
|
|||||||
@@ -16,123 +16,60 @@ type RenderBuildOpts struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildRenderData(opts RenderBuildOpts) (RenderData, error) {
|
func buildRenderData(opts RenderBuildOpts) (RenderData, error) {
|
||||||
builder := &renderDataBuilder{
|
rd := RenderData{
|
||||||
opts: opts,
|
|
||||||
data: RenderData{
|
|
||||||
PackageName: opts.PackageName,
|
PackageName: opts.PackageName,
|
||||||
ProjectPackage: opts.ProjectPackage,
|
ProjectPackage: opts.ProjectPackage,
|
||||||
Imports: []string{},
|
Imports: []string{},
|
||||||
Controllers: []string{},
|
Controllers: []string{},
|
||||||
Routes: make(map[string][]Router),
|
Routes: make(map[string][]Router),
|
||||||
RouteGroups: []string{},
|
RouteGroups: []string{},
|
||||||
},
|
|
||||||
imports: []string{},
|
|
||||||
controllers: []string{},
|
|
||||||
needsFieldImport: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build()
|
imports := []string{}
|
||||||
}
|
controllers := []string{}
|
||||||
|
|
||||||
type renderDataBuilder struct {
|
for _, route := range opts.Routes {
|
||||||
opts RenderBuildOpts
|
imports = append(imports, route.Imports...)
|
||||||
data RenderData
|
controllers = append(controllers, fmt.Sprintf("%s *%s", strcase.ToLowerCamel(route.Name), route.Name))
|
||||||
imports []string
|
|
||||||
controllers []string
|
|
||||||
needsFieldImport bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) build() (RenderData, error) {
|
|
||||||
b.processRoutes()
|
|
||||||
b.addRequiredImports()
|
|
||||||
b.dedupeAndSortImports()
|
|
||||||
b.dedupeAndSortControllers()
|
|
||||||
b.sortRouteGroups()
|
|
||||||
|
|
||||||
return b.data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) processRoutes() {
|
|
||||||
for _, route := range b.opts.Routes {
|
|
||||||
b.collectRouteMetadata(route)
|
|
||||||
b.buildRouteActions(route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) collectRouteMetadata(route RouteDefinition) {
|
|
||||||
b.imports = append(b.imports, route.Imports...)
|
|
||||||
b.controllers = append(b.controllers, fmt.Sprintf("%s *%s", strcase.ToLowerCamel(route.Name), route.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) buildRouteActions(route RouteDefinition) {
|
|
||||||
for _, action := range route.Actions {
|
for _, action := range route.Actions {
|
||||||
router := b.buildRouter(route, action)
|
funcName := fmt.Sprintf("Func%d", len(action.Params))
|
||||||
b.data.Routes[route.Name] = append(b.data.Routes[route.Name], router)
|
if action.HasData {
|
||||||
|
funcName = "Data" + funcName
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) buildRouter(route RouteDefinition, action ActionDefinition) Router {
|
params := lo.FilterMap(action.Params, func(item ParamDefinition, _ int) (string, bool) {
|
||||||
funcName := b.generateFunctionName(action)
|
tok := buildParamToken(item)
|
||||||
params := b.buildParameters(action.Params)
|
if tok == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return tok, true
|
||||||
|
})
|
||||||
|
|
||||||
return Router{
|
rd.Routes[route.Name] = append(rd.Routes[route.Name], Router{
|
||||||
Method: strcase.ToCamel(action.Method),
|
Method: strcase.ToCamel(action.Method),
|
||||||
Route: action.Route,
|
Route: action.Route,
|
||||||
Controller: strcase.ToLowerCamel(route.Name),
|
Controller: strcase.ToLowerCamel(route.Name),
|
||||||
Action: action.Name,
|
Action: action.Name,
|
||||||
Func: funcName,
|
Func: funcName,
|
||||||
Params: params,
|
Params: params,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) generateFunctionName(action ActionDefinition) string {
|
|
||||||
funcName := fmt.Sprintf("Func%d", len(action.Params))
|
|
||||||
if action.HasData {
|
|
||||||
funcName = "Data" + funcName
|
|
||||||
}
|
|
||||||
return funcName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) buildParameters(params []ParamDefinition) []string {
|
|
||||||
return lo.FilterMap(params, func(item ParamDefinition, _ int) (string, bool) {
|
|
||||||
token := buildParamToken(item)
|
|
||||||
if token == "" {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
return token, true
|
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) addRequiredImports() {
|
|
||||||
// New Model interface doesn't require field import
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) dedupeAndSortImports() {
|
|
||||||
b.data.Imports = lo.Uniq(b.imports)
|
|
||||||
sort.Strings(b.data.Imports)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) dedupeAndSortControllers() {
|
|
||||||
b.data.Controllers = lo.Uniq(b.controllers)
|
|
||||||
sort.Strings(b.data.Controllers)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) sortRouteGroups() {
|
|
||||||
// Collect route groups
|
|
||||||
for k := range b.data.Routes {
|
|
||||||
b.data.RouteGroups = append(b.data.RouteGroups, k)
|
|
||||||
}
|
}
|
||||||
sort.Strings(b.data.RouteGroups)
|
|
||||||
|
|
||||||
// Sort routes within each group
|
|
||||||
for _, groupName := range b.data.RouteGroups {
|
|
||||||
items := b.data.Routes[groupName]
|
|
||||||
b.sortRouteItems(items)
|
|
||||||
b.data.Routes[groupName] = items
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (b *renderDataBuilder) sortRouteItems(items []Router) {
|
// de-dup and sort imports/controllers for stable output
|
||||||
|
rd.Imports = lo.Uniq(imports)
|
||||||
|
sort.Strings(rd.Imports)
|
||||||
|
rd.Controllers = lo.Uniq(controllers)
|
||||||
|
sort.Strings(rd.Controllers)
|
||||||
|
|
||||||
|
// stable order for route groups and entries
|
||||||
|
for k := range rd.Routes {
|
||||||
|
rd.RouteGroups = append(rd.RouteGroups, k)
|
||||||
|
}
|
||||||
|
sort.Strings(rd.RouteGroups)
|
||||||
|
for _, k := range rd.RouteGroups {
|
||||||
|
items := rd.Routes[k]
|
||||||
sort.Slice(items, func(i, j int) bool {
|
sort.Slice(items, func(i, j int) bool {
|
||||||
if items[i].Method != items[j].Method {
|
if items[i].Method != items[j].Method {
|
||||||
return items[i].Method < items[j].Method
|
return items[i].Method < items[j].Method
|
||||||
@@ -142,124 +79,60 @@ func (b *renderDataBuilder) sortRouteItems(items []Router) {
|
|||||||
}
|
}
|
||||||
return items[i].Action < items[j].Action
|
return items[i].Action < items[j].Action
|
||||||
})
|
})
|
||||||
|
rd.Routes[k] = items
|
||||||
|
}
|
||||||
|
|
||||||
|
return rd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildParamToken(item ParamDefinition) string {
|
func buildParamToken(item ParamDefinition) string {
|
||||||
key := item.getKey()
|
key := item.Name
|
||||||
builder := ¶mTokenBuilder{item: item, key: key}
|
|
||||||
return builder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (item ParamDefinition) getKey() string {
|
|
||||||
if item.Key != "" {
|
if item.Key != "" {
|
||||||
return item.Key
|
key = item.Key
|
||||||
}
|
}
|
||||||
return item.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
type paramTokenBuilder struct {
|
switch item.Position {
|
||||||
item ParamDefinition
|
|
||||||
key string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) build() string {
|
|
||||||
switch b.item.Position {
|
|
||||||
case PositionQuery:
|
case PositionQuery:
|
||||||
return b.buildQueryParam()
|
return fmt.Sprintf(`Query%s[%s]("%s")`, scalarSuffix(item.Type), item.Type, key)
|
||||||
case PositionHeader:
|
case PositionHeader:
|
||||||
return b.buildHeaderParam()
|
return fmt.Sprintf(`Header[%s]("%s")`, item.Type, key)
|
||||||
case PositionFile:
|
case PositionFile:
|
||||||
return b.buildFileParam()
|
return fmt.Sprintf(`File[multipart.FileHeader]("%s")`, key)
|
||||||
case PositionCookie:
|
case PositionCookie:
|
||||||
return b.buildCookieParam()
|
if item.Type == "string" {
|
||||||
|
return fmt.Sprintf(`CookieParam("%s")`, key)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(`Cookie[%s]("%s")`, item.Type, key)
|
||||||
case PositionBody:
|
case PositionBody:
|
||||||
return b.buildBodyParam()
|
return fmt.Sprintf(`Body[%s]("%s")`, item.Type, key)
|
||||||
case PositionPath:
|
case PositionPath:
|
||||||
return b.buildPathParam()
|
// If a model field is specified, generate a model-lookup binder from path value.
|
||||||
case PositionLocal:
|
if item.Model != "" {
|
||||||
return b.buildLocalParam()
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) buildQueryParam() string {
|
|
||||||
return fmt.Sprintf(`Query%s[%s]("%s")`, scalarSuffix(b.item.Type), b.item.Type, b.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) buildHeaderParam() string {
|
|
||||||
return fmt.Sprintf(`Header[%s]("%s")`, b.item.Type, b.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) buildFileParam() string {
|
|
||||||
return fmt.Sprintf(`File[multipart.FileHeader]("%s")`, b.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) buildCookieParam() string {
|
|
||||||
if b.item.Type == "string" {
|
|
||||||
return fmt.Sprintf(`CookieParam("%s")`, b.key)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(`Cookie[%s]("%s")`, b.item.Type, b.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) buildBodyParam() string {
|
|
||||||
return fmt.Sprintf(`Body[%s]("%s")`, b.item.Type, b.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) buildPathParam() string {
|
|
||||||
if b.item.Model != "" {
|
|
||||||
return b.buildModelLookupPath()
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(`Path%s[%s]("%s")`, scalarSuffix(b.item.Type), b.item.Type, b.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) buildModelLookupPath() string {
|
|
||||||
field, _ := b.parseModelField()
|
|
||||||
|
|
||||||
// Use the simplified Model interface without closures
|
|
||||||
// This provides consistency with other parameter binding methods
|
|
||||||
if field == "id" && b.key == "id" {
|
|
||||||
// Use the simplest form for default id field
|
|
||||||
return fmt.Sprintf(`ModelById[%s]("%s")`, b.item.Type, b.key)
|
|
||||||
} else if field == b.key {
|
|
||||||
// Field and path key are the same
|
|
||||||
return fmt.Sprintf(`Model[%s]("%s")`, b.item.Type, field)
|
|
||||||
} else {
|
|
||||||
// Different field and path key
|
|
||||||
return fmt.Sprintf(`Model[%s]("%s", "%s")`, b.item.Type, field, b.key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getModelName extracts the model name from the type, preserving package path
|
|
||||||
func (b *paramTokenBuilder) getModelName() string {
|
|
||||||
// Remove the pointer star if present
|
|
||||||
typeName := strings.TrimPrefix(b.item.Type, "*")
|
|
||||||
|
|
||||||
// Keep the full package path for the query object
|
|
||||||
// e.g., "models.User" becomes "models.UserQuery"
|
|
||||||
return typeName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *paramTokenBuilder) parseModelField() (string, string) {
|
|
||||||
field := "id"
|
field := "id"
|
||||||
fieldType := "int"
|
fieldType := "int"
|
||||||
|
if strings.Contains(item.Model, ":") {
|
||||||
if strings.Contains(b.item.Model, ":") {
|
parts := strings.SplitN(item.Model, ":", 2)
|
||||||
parts := strings.SplitN(b.item.Model, ":", 2)
|
|
||||||
if len(parts) == 2 {
|
if len(parts) == 2 {
|
||||||
field = parts[0]
|
field = parts[0]
|
||||||
fieldType = parts[1]
|
fieldType = parts[1]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
field = b.item.Model
|
field = item.Model
|
||||||
}
|
}
|
||||||
|
|
||||||
return field, fieldType
|
tpl := `func(ctx fiber.Ctx) (*%s, error) {
|
||||||
|
v := fiber.Params[%s](ctx, "%s")
|
||||||
|
return %sQuery.WithContext(ctx).Where(field.NewUnsafeFieldRaw("%s = ?", v)).First()
|
||||||
|
}`
|
||||||
|
return fmt.Sprintf(tpl, item.Type, fieldType, key, item.Type, field)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(`Path%s[%s]("%s")`, scalarSuffix(item.Type), item.Type, key)
|
||||||
|
case PositionLocal:
|
||||||
|
return fmt.Sprintf(`Local[%s]("%s")`, item.Type, key)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *paramTokenBuilder) buildLocalParam() string {
|
|
||||||
return fmt.Sprintf(`Local[%s]("%s")`, b.item.Type, b.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func scalarSuffix(t string) string {
|
func scalarSuffix(t string) string {
|
||||||
switch t {
|
switch t {
|
||||||
|
|||||||
@@ -30,140 +30,24 @@ type Router struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Render(path string, routes []RouteDefinition) error {
|
func Render(path string, routes []RouteDefinition) error {
|
||||||
// Validate input parameters
|
routePath := filepath.Join(path, "routes.gen.go")
|
||||||
if err := validateRenderInput(path, routes); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer := &routeRenderer{
|
|
||||||
path: path,
|
|
||||||
routes: routes,
|
|
||||||
}
|
|
||||||
|
|
||||||
return renderer.render()
|
|
||||||
}
|
|
||||||
|
|
||||||
type routeRenderer struct {
|
|
||||||
path string
|
|
||||||
routes []RouteDefinition
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *routeRenderer) render() error {
|
|
||||||
// Prepare render data
|
|
||||||
data, err := r.prepareRenderData()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate content
|
|
||||||
content, err := r.generateContent(data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write to file atomically
|
|
||||||
return r.writeFileAtomically(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *routeRenderer) prepareRenderData() (RenderData, error) {
|
|
||||||
data, err := buildRenderData(RenderBuildOpts{
|
data, err := buildRenderData(RenderBuildOpts{
|
||||||
PackageName: filepath.Base(r.path),
|
PackageName: filepath.Base(path),
|
||||||
ProjectPackage: getProjectPackageWithFallback(),
|
ProjectPackage: gomod.GetModuleName(),
|
||||||
Routes: r.routes,
|
Routes: routes,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return RenderData{}, WrapError(err, "failed to build render data for path: %s", r.path)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the generated data
|
out, err := renderTemplate(data)
|
||||||
if err := r.validateRenderData(data); err != nil {
|
|
||||||
return RenderData{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *routeRenderer) validateRenderData(data RenderData) error {
|
|
||||||
if data.PackageName == "" {
|
|
||||||
return NewRouteError(ErrInvalidInput, "package name cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(data.Routes) == 0 {
|
|
||||||
return NewRouteError(ErrNoRoutes, "no routes to render")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that all routes have required fields
|
|
||||||
for controllerName, routes := range data.Routes {
|
|
||||||
if controllerName == "" {
|
|
||||||
return NewRouteError(ErrInvalidInput, "controller name cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, route := range routes {
|
|
||||||
if route.Method == "" {
|
|
||||||
return NewRouteError(ErrInvalidInput, "route method cannot be empty for controller %s, route %d", controllerName, i)
|
|
||||||
}
|
|
||||||
if route.Route == "" {
|
|
||||||
return NewRouteError(ErrInvalidInput, "route path cannot be empty for controller %s, route %d", controllerName, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *routeRenderer) generateContent(data RenderData) ([]byte, error) {
|
|
||||||
content, err := renderTemplate(data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, WrapError(err, "failed to render template for path: %s", r.path)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate generated content is not empty
|
if err := os.WriteFile(routePath, out, 0o644); err != nil {
|
||||||
if len(content) == 0 {
|
return err
|
||||||
return nil, NewRouteError(ErrTemplateFailed, "generated content is empty")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return content, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *routeRenderer) writeFileAtomically(content []byte) error {
|
|
||||||
routePath := filepath.Join(r.path, "routes.gen.go")
|
|
||||||
|
|
||||||
// Write to temporary file first for atomic operation
|
|
||||||
tempPath := routePath + ".tmp"
|
|
||||||
if err := os.WriteFile(tempPath, content, 0o644); err != nil {
|
|
||||||
return WrapError(err, "failed to write temporary route file: %s", tempPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename temporary file to final destination (atomic operation)
|
|
||||||
if err := os.Rename(tempPath, routePath); err != nil {
|
|
||||||
// Clean up temporary file if rename fails
|
|
||||||
_ = os.Remove(tempPath)
|
|
||||||
return WrapError(err, "failed to rename temporary file to final destination: %s -> %s", tempPath, routePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateRenderInput(path string, routes []RouteDefinition) error {
|
|
||||||
if path == "" {
|
|
||||||
return NewRouteError(ErrInvalidInput, "path cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
||||||
return NewRouteError(ErrInvalidPath, "directory does not exist: %s", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(routes) == 0 {
|
|
||||||
// This is not necessarily an error, but worth noting
|
|
||||||
return NewRouteError(ErrNoRoutes, "no routes provided for rendering")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getProjectPackageWithFallback() string {
|
|
||||||
if moduleName := gomod.GetModuleName(); moduleName != "" {
|
|
||||||
return moduleName
|
|
||||||
}
|
|
||||||
return "unknown" // fallback to prevent crashes
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type RouteDefinition struct {
|
type RouteDefinition struct {
|
||||||
FilePath string
|
|
||||||
Path string
|
Path string
|
||||||
Name string
|
Name string
|
||||||
Imports []string
|
Imports []string
|
||||||
@@ -138,7 +137,7 @@ func (p *routeParser) initializeRoute(recvType string) {
|
|||||||
if _, exists := p.routes[recvType]; !exists {
|
if _, exists := p.routes[recvType]; !exists {
|
||||||
p.routes[recvType] = RouteDefinition{
|
p.routes[recvType] = RouteDefinition{
|
||||||
Name: recvType,
|
Name: recvType,
|
||||||
FilePath: p.file,
|
Path: p.file,
|
||||||
Actions: []ActionDefinition{},
|
Actions: []ActionDefinition{},
|
||||||
}
|
}
|
||||||
p.actions[recvType] = []ActionDefinition{}
|
p.actions[recvType] = []ActionDefinition{}
|
||||||
@@ -257,12 +256,6 @@ func (p *routeParser) buildResult() []RouteDefinition {
|
|||||||
if actions, exists := p.actions[k]; exists {
|
if actions, exists := p.actions[k]; exists {
|
||||||
route.Actions = actions
|
route.Actions = actions
|
||||||
route.Imports = p.getUniqueImports(k)
|
route.Imports = p.getUniqueImports(k)
|
||||||
|
|
||||||
// Set the route path from the first action for backward compatibility
|
|
||||||
if len(actions) > 0 {
|
|
||||||
route.Path = actions[0].Route
|
|
||||||
}
|
|
||||||
|
|
||||||
items = append(items, route)
|
items = append(items, route)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user