Skip to content

Commit

Permalink
cmd: improve nested types generation (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
hgiasac authored Jun 20, 2024
1 parent 8c29ab1 commit 245640d
Show file tree
Hide file tree
Showing 12 changed files with 1,246 additions and 1,135 deletions.
71 changes: 37 additions & 34 deletions cmd/hasura-ndc-go/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,13 @@ func (cg *connectorGenerator) genConnectorFunctions(rawSchema *RawConnectorSchem
}`)
}

if fn.ArgumentsType != "" {
if fn.ArgumentsType != nil {
argName := fn.ArgumentsType.Name
if fn.ArgumentsType.PackagePath != "" {
cg.rawSchema.Imports[fn.ArgumentsType.PackagePath] = true
argName = fmt.Sprintf("%s.%s", fn.ArgumentsType.PackageName, fn.ArgumentsType.Name)
}

argumentStr := fmt.Sprintf(`
rawArgs, err := utils.ResolveArgumentVariables(request.Arguments, variables)
if err != nil {
Expand All @@ -208,7 +214,7 @@ func (cg *connectorGenerator) genConnectorFunctions(rawSchema *RawConnectorSchem
"raw_arguments": rawArgs,
})
var args %s.%s
var args %s
if err = args.FromValue(rawArgs); err != nil {
return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{
"cause": err.Error(),
Expand All @@ -217,7 +223,7 @@ func (cg *connectorGenerator) genConnectorFunctions(rawSchema *RawConnectorSchem
connector_addSpanEvent(span, logger, "execute_function", map[string]any{
"arguments": args,
})`, fn.PackageName, fn.ArgumentsType)
})`, argName)
sb.WriteString(argumentStr)
argumentParamStr = ", &args"
}
Expand Down Expand Up @@ -299,14 +305,20 @@ func (cg *connectorGenerator) genConnectorProcedures(rawSchema *RawConnectorSche
})
}`)
}
if fn.ArgumentsType != "" {
if fn.ArgumentsType != nil {
argName := fn.ArgumentsType.Name
if fn.ArgumentsType.PackagePath != "" {
cg.rawSchema.Imports[fn.ArgumentsType.PackagePath] = true
argName = fmt.Sprintf("%s.%s", fn.ArgumentsType.PackageName, fn.ArgumentsType.Name)
}

argumentStr := fmt.Sprintf(`
var args %s.%s
var args %s
if err := json.Unmarshal(operation.Arguments, &args); err != nil {
return nil, schema.UnprocessableContentError("failed to decode arguments", map[string]any{
"cause": err.Error(),
})
}`, fn.PackageName, fn.ArgumentsType)
}`, argName)
sb.WriteString(argumentStr)
argumentParamStr = ", &args"
}
Expand Down Expand Up @@ -349,7 +361,7 @@ func (cg *connectorGenerator) genTypeMethods() error {
return err
}

log.Debug().Msg("generating types...")
log.Debug().Msg("Generating types...")
for packagePath, builder := range cg.typeBuilders {
relativePath := strings.TrimPrefix(packagePath, cg.moduleName)
schemaPath := path.Join(cg.basePath, relativePath, typeMethodsOutputFile)
Expand Down Expand Up @@ -435,7 +447,7 @@ func (cg *connectorGenerator) genToMapProperty(sb *connectorTypeBuilder, field *
}
innerObject, ok := cg.rawSchema.Objects[ty.Name]
if !ok {
_, tyName := buildTypeNameFromFragments(ty.TypeFragments, sb.packagePath)
tyName := buildTypeNameFromFragments(ty.TypeFragments, ty.PackagePath, sb.packagePath)
innerObject, ok = cg.rawSchema.Objects[tyName]
if !ok {
return selector
Expand Down Expand Up @@ -554,15 +566,15 @@ func (cg *connectorGenerator) genFunctionArgumentConstructors() error {
}

for _, fn := range cg.rawSchema.Functions {
if len(fn.Arguments) == 0 {
if len(fn.Arguments) == 0 || fn.ArgumentsType == nil {
continue
}
sb := cg.getOrCreateTypeBuilder(fn.PackagePath)
sb := cg.getOrCreateTypeBuilder(fn.ArgumentsType.PackagePath)
sb.builder.WriteString(fmt.Sprintf(`
// FromValue decodes values from map
func (j *%s) FromValue(input map[string]any) error {
var err error
`, fn.ArgumentsType))
`, fn.ArgumentsType.Name))

argumentKeys := getSortedKeys(fn.Arguments)
for _, key := range argumentKeys {
Expand Down Expand Up @@ -743,9 +755,10 @@ func (cg *connectorGenerator) genGetTypeValueDecoder(sb *connectorTypeBuilder, t
typeName := strings.TrimLeft(typeName, "*")
pkgName, tyName, ok := findAndReplaceNativeScalarPackage(typeName)
if !ok {
pkgName, tyName = buildTypeNameFromFragments(ty.TypeFragments[1:], sb.packagePath)
pkgName = ty.PackagePath
tyName = buildTypeNameFromFragments(ty.TypeFragments[1:], ty.PackagePath, sb.packagePath)
}
if pkgName != "" {
if pkgName != "" && pkgName != sb.packagePath {
sb.imports[pkgName] = ""
}
sb.builder.WriteString(fmt.Sprintf(` j.%s = new(%s)
Expand All @@ -757,39 +770,29 @@ func (cg *connectorGenerator) genGetTypeValueDecoder(sb *connectorTypeBuilder, t
sb.builder.WriteString(textBlockErrorCheck)
}

func buildTypeNameFromFragments(items []string, packagePath string) (string, string) {
func buildTypeNameFromFragments(items []string, typePackagePath string, currentPackagePath string) string {
results := make([]string, len(items))
importModule := ""
for i, item := range items {
if item == "*" || item == "[]" {
results[i] = item
continue
}
importModule, results[i] = extractPackageAndTypeName(item, packagePath)
results[i] = buildTypeWithAlias(item, typePackagePath, currentPackagePath)
}

return importModule, strings.Join(results, "")
return strings.Join(results, "")
}

func extractPackageAndTypeName(name string, packagePath string) (string, string) {
if packagePath != "" {
packagePath = fmt.Sprintf("%s.", packagePath)
}

if packagePath != "" && strings.HasPrefix(name, packagePath) {
return "", strings.ReplaceAll(name, packagePath, "")
}
parts := strings.Split(name, "/")
typeName := parts[len(parts)-1]
typeNameParts := strings.Split(typeName, ".")
if len(typeNameParts) < 2 {
return "", typeName
}
if len(parts) == 1 {
return typeNameParts[0], typeName
func buildTypeWithAlias(name string, typePackagePath string, currentPackagePath string) string {
if typePackagePath == "" || typePackagePath == currentPackagePath ||
// do not add alias to anonymous struct
strings.HasPrefix(name, "struct{") {
return name
}

return strings.Join(append(parts[:len(parts)-1], typeNameParts[0]), "/"), typeName
parts := strings.Split(typePackagePath, "/")
alias := parts[len(parts)-1]
return fmt.Sprintf("%s.%s", alias, name)
}

func getSortedKeys[V any](input map[string]V) []string {
Expand Down
3 changes: 1 addition & 2 deletions cmd/hasura-ndc-go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type GenerateArguments struct {
Path string `help:"The path of the root directory where the go.mod file is present" short:"p" default:"."`
ConnectorDir string `help:"The directory where the connector.go file is placed" default:"."`
PackageTypes string `help:"The name of types package where the State struct is in"`
Directories []string `help:"Folders contain NDC operation functions" short:"d" default:"functions,types"`
Directories []string `help:"Folders contain NDC operation functions" short:"d"`
Trace string `help:"Enable tracing and write to target file path."`
}

Expand Down Expand Up @@ -66,7 +66,6 @@ func main() {
Str("path", cli.Generate.Path).
Str("connector_dir", cli.Generate.ConnectorDir).
Str("package_types", cli.Generate.PackageTypes).
Interface("directories", cli.Generate.Directories).
Msg("generating connector schema...")

moduleName, err := getModuleName(cli.Generate.Path)
Expand Down
Loading

0 comments on commit 245640d

Please sign in to comment.