diff --git a/cmd/hasura-ndc-go/command/internal/connector.go b/cmd/hasura-ndc-go/command/internal/connector.go index b3256cc..94a025e 100644 --- a/cmd/hasura-ndc-go/command/internal/connector.go +++ b/cmd/hasura-ndc-go/command/internal/connector.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "go/token" + "go/types" "io" "os" "path" @@ -61,7 +62,6 @@ func (ctb connectorTypeBuilder) String() string { bs.WriteString(")\n") } - bs.WriteString("var connector_Decoder = utils.NewDecoder()\n") bs.WriteString(ctb.builder.String()) return bs.String() } @@ -642,51 +642,61 @@ func (cg *connectorGenerator) writeGetTypeValueDecoder(sb *connectorTypeBuilder, case "*[]*any", "*[]*interface{}": cg.writeScalarDecodeValue(sb, fieldName, "GetNullableArbitraryJSONPtrSlice", "", key, objectField, true) default: + sb.builder.WriteString(" j.") + sb.builder.WriteString(fieldName) + sb.builder.WriteString(", err = utils.") switch t := ty.(type) { case *NullableType: - packagePaths := getTypePackagePaths(t.UnderlyingType, sb.packagePath) - tyName := getTypeArgumentName(t.UnderlyingType, sb.packagePath, false) - + var tyName string + var packagePaths []string + if t.IsAnonymous() { + tyName, packagePaths = cg.getAnonymousObjectTypeName(sb, field.TypeAST, true) + } else { + packagePaths = getTypePackagePaths(t.UnderlyingType, sb.packagePath) + tyName = getTypeArgumentName(t.UnderlyingType, sb.packagePath, false) + } for _, pkgPath := range packagePaths { sb.imports[pkgPath] = "" } - sb.builder.WriteString(" j.") - sb.builder.WriteString(fieldName) - sb.builder.WriteString(" = new(") - sb.builder.WriteString(tyName) - sb.builder.WriteString(")\n err = connector_Decoder.") if field.Embedded { - sb.builder.WriteString("DecodeObject(j.") - sb.builder.WriteString(fieldName) - sb.builder.WriteString(", input)") + sb.builder.WriteString("DecodeNullableObject[") + sb.builder.WriteString(tyName) + sb.builder.WriteString("](input)") } else { - sb.builder.WriteString("DecodeNullableObjectValue(j.") - sb.builder.WriteString(fieldName) - sb.builder.WriteString(`, input, "`) + sb.builder.WriteString("DecodeNullableObjectValue[") + sb.builder.WriteString(tyName) + sb.builder.WriteString(`](input, "`) sb.builder.WriteString(key) sb.builder.WriteString(`")`) } default: - var canEmpty bool - if len(objectField.Type) > 0 { - if typeEnum, err := objectField.Type.Type(); err == nil && typeEnum == schema.TypeNullable { - canEmpty = true - } + var tyName string + var packagePaths []string + if t.IsAnonymous() { + tyName, packagePaths = cg.getAnonymousObjectTypeName(sb, field.TypeAST, true) + } else { + packagePaths = getTypePackagePaths(ty, sb.packagePath) + tyName = getTypeArgumentName(ty, sb.packagePath, false) + } + for _, pkgPath := range packagePaths { + sb.imports[pkgPath] = "" } + if field.Embedded { - sb.builder.WriteString(" err = connector_Decoder.DecodeObject(&j.") - sb.builder.WriteString(fieldName) - sb.builder.WriteString(", input)") + sb.builder.WriteString("DecodeObject") + sb.builder.WriteRune('[') + sb.builder.WriteString(tyName) + sb.builder.WriteString("](input)") } else { - sb.builder.WriteString(" err = connector_Decoder.") - if canEmpty { - sb.builder.WriteString("DecodeNullableObjectValue") - } else { - sb.builder.WriteString("DecodeObjectValue") + sb.builder.WriteString("DecodeObjectValue") + if len(objectField.Type) > 0 { + if typeEnum, err := objectField.Type.Type(); err == nil && typeEnum == schema.TypeNullable { + sb.builder.WriteString("Default") + } } - sb.builder.WriteString("(&j.") - sb.builder.WriteString(fieldName) - sb.builder.WriteString(`, input, "`) + sb.builder.WriteRune('[') + sb.builder.WriteString(tyName) + sb.builder.WriteString(`](input, "`) sb.builder.WriteString(key) sb.builder.WriteString(`")`) } @@ -715,6 +725,86 @@ func (cg *connectorGenerator) writeScalarDecodeValue(sb *connectorTypeBuilder, f sb.builder.WriteString(`")`) } +// generate anonymous object type name with absolute package paths removed +func (cg *connectorGenerator) getAnonymousObjectTypeName(sb *connectorTypeBuilder, goType types.Type, skipNullable bool) (string, []string) { + switch inferredType := goType.(type) { + case *types.Pointer: + var result string + if !skipNullable { + result += "*" + } + underlyingName, packagePaths := cg.getAnonymousObjectTypeName(sb, inferredType.Elem(), false) + return result + underlyingName, packagePaths + case *types.Struct: + packagePaths := []string{} + result := "struct{" + for i := 0; i < inferredType.NumFields(); i++ { + fieldVar := inferredType.Field(i) + fieldTag := inferredType.Tag(i) + if i > 0 { + result += "; " + } + result += fieldVar.Name() + " " + underlyingName, pkgPaths := cg.getAnonymousObjectTypeName(sb, fieldVar.Type(), false) + result += underlyingName + packagePaths = append(packagePaths, pkgPaths...) + if fieldTag != "" { + result += " `" + fieldTag + "`" + } + } + result += "}" + return result, packagePaths + case *types.Named: + packagePaths := []string{} + innerType := inferredType.Obj() + if innerType == nil { + return "", packagePaths + } + + var result string + typeInfo := &TypeInfo{ + Name: innerType.Name(), + } + + innerPkg := innerType.Pkg() + if innerPkg != nil && innerPkg.Name() != "" && innerPkg.Path() != sb.packagePath { + packagePaths = append(packagePaths, innerPkg.Path()) + result += innerPkg.Name() + "." + typeInfo.PackageName = innerPkg.Name() + typeInfo.PackagePath = innerPkg.Path() + } + + result += innerType.Name() + typeParams := inferredType.TypeParams() + if typeParams != nil && typeParams.Len() > 0 { + // unwrap the generic type parameters such as Foo[T] + if err := parseTypeParameters(typeInfo, inferredType.String()); err == nil { + result += "[" + for i, typeParam := range typeInfo.TypeParameters { + if i > 0 { + result += ", " + } + packagePaths = append(packagePaths, getTypePackagePaths(typeParam, sb.packagePath)...) + result += getTypeArgumentName(typeParam, sb.packagePath, false) + } + result += "]" + } + } + + return result, packagePaths + case *types.Basic: + return inferredType.Name(), []string{} + case *types.Array: + result, packagePaths := cg.getAnonymousObjectTypeName(sb, inferredType.Elem(), false) + return "[]" + result, packagePaths + case *types.Slice: + result, packagePaths := cg.getAnonymousObjectTypeName(sb, inferredType.Elem(), false) + return "[]" + result, packagePaths + default: + return inferredType.String(), []string{} + } +} + func formatLocalFieldName(input string, others ...string) string { name := fieldNameRegex.ReplaceAllString(input, "_") return strings.Trim(strings.Join(append([]string{name}, others...), "_"), "_") diff --git a/cmd/hasura-ndc-go/command/internal/connector_handler.go b/cmd/hasura-ndc-go/command/internal/connector_handler.go index 6a7d1b8..c8b00d5 100644 --- a/cmd/hasura-ndc-go/command/internal/connector_handler.go +++ b/cmd/hasura-ndc-go/command/internal/connector_handler.go @@ -131,16 +131,18 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *`) chb.Builder.imports[fn.ArgumentsType.PackagePath] = "" } - sb.WriteString(` - var args `) - sb.WriteString(argName) - sb.WriteString("\n if parseErr := ") if fn.ArgumentsType.CanMethod() { + sb.WriteString("\n var args ") + sb.WriteString(argName) + sb.WriteString("\n parseErr := ") sb.WriteString("args.FromValue(rawArgs)") } else { - sb.WriteString("connector_Decoder.DecodeObject(&args, rawArgs)") + sb.WriteString("\n args, parseErr := utils.DecodeObject[") + sb.WriteString(argName) + sb.WriteString("](rawArgs)") } - sb.WriteString(`; parseErr != nil { + sb.WriteString(` + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) diff --git a/cmd/hasura-ndc-go/command/internal/schema.go b/cmd/hasura-ndc-go/command/internal/schema.go index 35f2cbd..4e9abce 100644 --- a/cmd/hasura-ndc-go/command/internal/schema.go +++ b/cmd/hasura-ndc-go/command/internal/schema.go @@ -7,6 +7,7 @@ import ( "github.com/hasura/ndc-sdk-go/schema" ) +// OperationKind the operation kind of connectors type OperationKind string const ( @@ -14,19 +15,23 @@ const ( OperationProcedure OperationKind = "Procedure" ) +// Scalar the structured information of the scalar type Scalar struct { Schema schema.ScalarType NativeType *TypeInfo } +// Type the interface of a type schema type Type interface { Kind() schema.TypeEnum Schema() schema.TypeEncoder SchemaName(isAbsolute bool) string FullName() string String() string + IsAnonymous() bool } +// NullableType the information of the nullable type type NullableType struct { UnderlyingType Type } @@ -41,6 +46,10 @@ func (t *NullableType) Kind() schema.TypeEnum { return schema.TypeNullable } +func (t *NullableType) IsAnonymous() bool { + return t.UnderlyingType.IsAnonymous() +} + func (t NullableType) SchemaName(isAbsolute bool) string { var result string if isAbsolute { @@ -65,6 +74,7 @@ func (t NullableType) String() string { return "*" + t.UnderlyingType.String() } +// ArrayType the information of the array type type ArrayType struct { ElementType Type } @@ -79,6 +89,10 @@ func (t *ArrayType) Kind() schema.TypeEnum { return schema.TypeArray } +func (t *ArrayType) IsAnonymous() bool { + return t.ElementType.IsAnonymous() +} + func (t *ArrayType) Schema() schema.TypeEncoder { return schema.NewArrayType(t.ElementType.Schema()) } @@ -100,6 +114,7 @@ func (t ArrayType) String() string { return "[]" + t.ElementType.String() } +// NamedType the information of a named type type NamedType struct { Name string NativeType *TypeInfo @@ -115,6 +130,10 @@ func (t *NamedType) Kind() schema.TypeEnum { return schema.TypeNamed } +func (t *NamedType) IsAnonymous() bool { + return t.NativeType.IsAnonymous +} + func (t *NamedType) Schema() schema.TypeEncoder { return schema.NewNamedType(t.Name) } @@ -209,6 +228,7 @@ type Field struct { Description *string Embedded bool Type Type + TypeAST types.Type } // ObjectInfo represents the serialization information of an object type. diff --git a/cmd/hasura-ndc-go/command/internal/schema_type_parser.go b/cmd/hasura-ndc-go/command/internal/schema_type_parser.go index 4699469..ad7ce02 100644 --- a/cmd/hasura-ndc-go/command/internal/schema_type_parser.go +++ b/cmd/hasura-ndc-go/command/internal/schema_type_parser.go @@ -34,6 +34,9 @@ func (tp *TypeParser) Parse(fieldPaths []string) (*Field, error) { if err != nil { return nil, err } + if ty == nil { + return nil, nil + } tp.field.Type = ty return tp.field, nil } @@ -314,6 +317,8 @@ func (tp *TypeParser) parseType(ty types.Type, fieldPaths []string) (Type, error }) return NewNamedType(string(ScalarJSON), typeInfo), nil + case *types.Chan, *types.Signature, *types.Tuple, *types.Union: + return nil, nil default: return nil, fmt.Errorf("unsupported type: %s", ty.String()) } @@ -322,6 +327,10 @@ func (tp *TypeParser) parseType(ty types.Type, fieldPaths []string) (Type, error func (tp *TypeParser) parseStructType(objectInfo *ObjectInfo, inferredType *types.Struct, fieldPaths []string) error { for i := 0; i < inferredType.NumFields(); i++ { fieldVar := inferredType.Field(i) + if !fieldVar.Exported() { + continue + } + fieldTag := inferredType.Tag(i) fieldKey, jsonOption := getFieldNameOrTag(fieldVar.Name(), fieldTag) if jsonOption == jsonIgnore { @@ -330,11 +339,15 @@ func (tp *TypeParser) parseStructType(objectInfo *ObjectInfo, inferredType *type fieldParser := NewTypeParser(tp.schemaParser, &Field{ Name: fieldVar.Name(), Embedded: fieldVar.Embedded(), + TypeAST: fieldVar.Type(), }, fieldVar.Type(), tp.argumentFor) field, err := fieldParser.Parse(append(fieldPaths, fieldVar.Name())) if err != nil { return err } + if field == nil { + continue + } embeddedObject, ok := tp.schemaParser.rawSchema.Objects[field.Type.SchemaName(false)] if field.Embedded && ok { // flatten embedded object fields to the parent object @@ -466,7 +479,13 @@ func (tp *TypeParser) parseTypeInfoFromComments(typeInfo *TypeInfo, scope *types func parseTypeParameters(rootType *TypeInfo, input string) error { paramsString := strings.TrimPrefix(input, rootType.PackagePath+"."+rootType.Name) - rawParams := strings.Split(paramsString[1:len(paramsString)-1], ",") + if paramsString[0] == '[' { + paramsString = paramsString[1:] + } + if paramsString[len(paramsString)-1] == ']' { + paramsString = paramsString[:len(paramsString)-1] + } + rawParams := strings.Split(paramsString, ",") for _, param := range rawParams { param = strings.TrimSpace(param) diff --git a/cmd/hasura-ndc-go/command/internal/schema_type_parser_test.go b/cmd/hasura-ndc-go/command/internal/schema_type_parser_test.go new file mode 100644 index 0000000..7cab30f --- /dev/null +++ b/cmd/hasura-ndc-go/command/internal/schema_type_parser_test.go @@ -0,0 +1,69 @@ +package internal + +import ( + "strconv" + "testing" + + "gotest.tools/v3/assert" +) + +func TestParseTypeFromString(t *testing.T) { + testCases := []struct { + Input string + Expected Type + }{ + { + Input: "[]*github.com/hasura/ndc-codegen-example/types.Author", + Expected: NewArrayType(NewNullableType(NewNamedType("Author", &TypeInfo{ + Name: "Author", + PackageName: "types", + PackagePath: "github.com/hasura/ndc-codegen-example/types", + }))), + }, + } + + for i, tc := range testCases { + t.Run(strconv.FormatInt(int64(i), 32), func(t *testing.T) { + result, err := parseTypeFromString(tc.Input) + assert.NilError(t, err) + assert.DeepEqual(t, tc.Expected, result) + }) + } +} + +func TestParseTypeParameters(t *testing.T) { + testCases := []struct { + Input string + Info TypeInfo + Expected TypeInfo + }{ + { + Input: "github.com/hasura/ndc-codegen-example/types.CustomHeadersResult[github.com/hasura/ndc-codegen-example/types.Author]", + Info: TypeInfo{ + PackagePath: "github.com/hasura/ndc-codegen-example/types", + Name: "CustomHeadersResult", + }, + Expected: TypeInfo{ + Name: "CustomHeadersResult", + PackagePath: "github.com/hasura/ndc-codegen-example/types", + SchemaName: "_Author", + TypeParameters: []Type{ + NewNamedType("Author", &TypeInfo{ + Name: "Author", + PackageName: "types", + PackagePath: "github.com/hasura/ndc-codegen-example/types", + }), + }, + }, + }, + } + + for i, tc := range testCases { + t.Run(strconv.FormatInt(int64(i), 32), func(t *testing.T) { + result := tc.Info + err := parseTypeParameters(&result, tc.Input) + assert.NilError(t, err) + assert.DeepEqual(t, tc.Expected, result) + }) + } +} diff --git a/cmd/hasura-ndc-go/command/internal/testdata/basic/expected/functions.go.tmpl b/cmd/hasura-ndc-go/command/internal/testdata/basic/expected/functions.go.tmpl index 0cb555c..2ae1979 100644 --- a/cmd/hasura-ndc-go/command/internal/testdata/basic/expected/functions.go.tmpl +++ b/cmd/hasura-ndc-go/command/internal/testdata/basic/expected/functions.go.tmpl @@ -15,7 +15,6 @@ import ( "slices" "time" ) -var connector_Decoder = utils.NewDecoder() // FromValue decodes values from map func (j *Author) FromValue(input map[string]any) error { @@ -51,11 +50,11 @@ func (j *GetArticlesArguments) FromValue(input map[string]any) error { // FromValue decodes values from map func (j *GetTypesArguments) FromValue(input map[string]any) error { var err error - err = connector_Decoder.DecodeObjectValue(&j.ArrayBigInt, input, "ArrayBigInt") + j.ArrayBigInt, err = utils.DecodeObjectValue[[]scalar.BigInt](input, "ArrayBigInt") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.ArrayBigIntPtr, input, "ArrayBigIntPtr") + j.ArrayBigIntPtr, err = utils.DecodeObjectValue[[]*scalar.BigInt](input, "ArrayBigIntPtr") if err != nil { return err } @@ -131,21 +130,19 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.ArrayMap, input, "ArrayMap") + j.ArrayMap, err = utils.DecodeObjectValue[[]map[string]any](input, "ArrayMap") if err != nil { return err } - j.ArrayMapPtr = new([]map[string]any) - err = connector_Decoder.DecodeNullableObjectValue(j.ArrayMapPtr, input, "ArrayMapPtr") + j.ArrayMapPtr, err = utils.DecodeNullableObjectValue[[]map[string]any](input, "ArrayMapPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.ArrayObject, input, "ArrayObject") + j.ArrayObject, err = utils.DecodeObjectValue[[]struct{Content string `json:"content"`}](input, "ArrayObject") if err != nil { return err } - j.ArrayObjectPtr = new([]struct{Content string "json:\"content\""}) - err = connector_Decoder.DecodeNullableObjectValue(j.ArrayObjectPtr, input, "ArrayObjectPtr") + j.ArrayObjectPtr, err = utils.DecodeNullableObjectValue[[]struct{Content string `json:"content"`}](input, "ArrayObjectPtr") if err != nil { return err } @@ -221,12 +218,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.BigInt, input, "BigInt") + j.BigInt, err = utils.DecodeObjectValue[scalar.BigInt](input, "BigInt") if err != nil { return err } - j.BigIntPtr = new(scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.BigIntPtr, input, "BigIntPtr") + j.BigIntPtr, err = utils.DecodeNullableObjectValue[scalar.BigInt](input, "BigIntPtr") if err != nil { return err } @@ -238,34 +234,31 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Bytes, input, "Bytes") + j.Bytes, err = utils.DecodeObjectValue[scalar.Bytes](input, "Bytes") if err != nil { return err } - j.BytesPtr = new(scalar.Bytes) - err = connector_Decoder.DecodeNullableObjectValue(j.BytesPtr, input, "BytesPtr") + j.BytesPtr, err = utils.DecodeNullableObjectValue[scalar.Bytes](input, "BytesPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.CustomScalar, input, "CustomScalar") + j.CustomScalar, err = utils.DecodeObjectValue[CommentText](input, "CustomScalar") if err != nil { return err } - j.CustomScalarPtr = new(CommentText) - err = connector_Decoder.DecodeNullableObjectValue(j.CustomScalarPtr, input, "CustomScalarPtr") + j.CustomScalarPtr, err = utils.DecodeNullableObjectValue[CommentText](input, "CustomScalarPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Duration, input, "Duration") + j.Duration, err = utils.DecodeObjectValue[scalar.Duration](input, "Duration") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Enum, input, "Enum") + j.Enum, err = utils.DecodeObjectValue[SomeEnum](input, "Enum") if err != nil { return err } - j.EnumPtr = new(SomeEnum) - err = connector_Decoder.DecodeNullableObjectValue(j.EnumPtr, input, "EnumPtr") + j.EnumPtr, err = utils.DecodeNullableObjectValue[SomeEnum](input, "EnumPtr") if err != nil { return err } @@ -333,54 +326,47 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Map, input, "Map") + j.Map, err = utils.DecodeObjectValue[map[string]any](input, "Map") if err != nil { return err } - j.MapPtr = new(map[string]any) - err = connector_Decoder.DecodeNullableObjectValue(j.MapPtr, input, "MapPtr") + j.MapPtr, err = utils.DecodeNullableObjectValue[map[string]any](input, "MapPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.NamedArray, input, "NamedArray") + j.NamedArray, err = utils.DecodeObjectValue[[]Author](input, "NamedArray") if err != nil { return err } - j.NamedArrayPtr = new([]Author) - err = connector_Decoder.DecodeNullableObjectValue(j.NamedArrayPtr, input, "NamedArrayPtr") + j.NamedArrayPtr, err = utils.DecodeNullableObjectValue[[]Author](input, "NamedArrayPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.NamedObject, input, "NamedObject") + j.NamedObject, err = utils.DecodeObjectValue[Author](input, "NamedObject") if err != nil { return err } - j.NamedObjectPtr = new(Author) - err = connector_Decoder.DecodeNullableObjectValue(j.NamedObjectPtr, input, "NamedObjectPtr") + j.NamedObjectPtr, err = utils.DecodeNullableObjectValue[Author](input, "NamedObjectPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Object, input, "Object") + j.Object, err = utils.DecodeObjectValue[struct{ID uuid.UUID `json:"id"`; CreatedAt time.Time `json:"created_at"`}](input, "Object") if err != nil { return err } - j.ObjectPtr = new(struct{Long int; Lat int}) - err = connector_Decoder.DecodeNullableObjectValue(j.ObjectPtr, input, "ObjectPtr") + j.ObjectPtr, err = utils.DecodeNullableObjectValue[struct{Long int; Lat int}](input, "ObjectPtr") if err != nil { return err } - j.PtrArrayBigInt = new([]scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBigInt, input, "PtrArrayBigInt") + j.PtrArrayBigInt, err = utils.DecodeNullableObjectValue[[]scalar.BigInt](input, "PtrArrayBigInt") if err != nil { return err } - j.PtrArrayBigIntPtr = new([]*scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBigIntPtr, input, "PtrArrayBigIntPtr") + j.PtrArrayBigIntPtr, err = utils.DecodeNullableObjectValue[[]*scalar.BigInt](input, "PtrArrayBigIntPtr") if err != nil { return err } - j.PtrArrayBool = new([]bool) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBool, input, "PtrArrayBool") + j.PtrArrayBool, err = utils.DecodeNullableObjectValue[[]bool](input, "PtrArrayBool") if err != nil { return err } @@ -388,8 +374,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayFloat32 = new([]float32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayFloat32, input, "PtrArrayFloat32") + j.PtrArrayFloat32, err = utils.DecodeNullableObjectValue[[]float32](input, "PtrArrayFloat32") if err != nil { return err } @@ -397,8 +382,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayFloat64 = new([]float64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayFloat64, input, "PtrArrayFloat64") + j.PtrArrayFloat64, err = utils.DecodeNullableObjectValue[[]float64](input, "PtrArrayFloat64") if err != nil { return err } @@ -406,13 +390,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayInt = new([]int) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt, input, "PtrArrayInt") + j.PtrArrayInt, err = utils.DecodeNullableObjectValue[[]int](input, "PtrArrayInt") if err != nil { return err } - j.PtrArrayInt16 = new([]int16) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt16, input, "PtrArrayInt16") + j.PtrArrayInt16, err = utils.DecodeNullableObjectValue[[]int16](input, "PtrArrayInt16") if err != nil { return err } @@ -420,8 +402,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayInt32 = new([]int32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt32, input, "PtrArrayInt32") + j.PtrArrayInt32, err = utils.DecodeNullableObjectValue[[]int32](input, "PtrArrayInt32") if err != nil { return err } @@ -429,8 +410,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayInt64 = new([]int64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt64, input, "PtrArrayInt64") + j.PtrArrayInt64, err = utils.DecodeNullableObjectValue[[]int64](input, "PtrArrayInt64") if err != nil { return err } @@ -438,8 +418,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayInt8 = new([]int8) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt8, input, "PtrArrayInt8") + j.PtrArrayInt8, err = utils.DecodeNullableObjectValue[[]int8](input, "PtrArrayInt8") if err != nil { return err } @@ -451,8 +430,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayJSON = new([]any) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayJSON, input, "PtrArrayJSON") + j.PtrArrayJSON, err = utils.DecodeNullableObjectValue[[]any](input, "PtrArrayJSON") if err != nil { return err } @@ -460,8 +438,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayRawJSON = new([]json.RawMessage) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayRawJSON, input, "PtrArrayRawJSON") + j.PtrArrayRawJSON, err = utils.DecodeNullableObjectValue[[]json.RawMessage](input, "PtrArrayRawJSON") if err != nil { return err } @@ -469,8 +446,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayString = new([]string) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayString, input, "PtrArrayString") + j.PtrArrayString, err = utils.DecodeNullableObjectValue[[]string](input, "PtrArrayString") if err != nil { return err } @@ -478,8 +454,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayTime = new([]time.Time) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayTime, input, "PtrArrayTime") + j.PtrArrayTime, err = utils.DecodeNullableObjectValue[[]time.Time](input, "PtrArrayTime") if err != nil { return err } @@ -487,8 +462,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUUID = new([]uuid.UUID) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUUID, input, "PtrArrayUUID") + j.PtrArrayUUID, err = utils.DecodeNullableObjectValue[[]uuid.UUID](input, "PtrArrayUUID") if err != nil { return err } @@ -496,13 +470,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUint = new([]uint) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint, input, "PtrArrayUint") + j.PtrArrayUint, err = utils.DecodeNullableObjectValue[[]uint](input, "PtrArrayUint") if err != nil { return err } - j.PtrArrayUint16 = new([]uint16) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint16, input, "PtrArrayUint16") + j.PtrArrayUint16, err = utils.DecodeNullableObjectValue[[]uint16](input, "PtrArrayUint16") if err != nil { return err } @@ -510,8 +482,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUint32 = new([]uint32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint32, input, "PtrArrayUint32") + j.PtrArrayUint32, err = utils.DecodeNullableObjectValue[[]uint32](input, "PtrArrayUint32") if err != nil { return err } @@ -519,8 +490,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUint64 = new([]uint64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint64, input, "PtrArrayUint64") + j.PtrArrayUint64, err = utils.DecodeNullableObjectValue[[]uint64](input, "PtrArrayUint64") if err != nil { return err } @@ -528,8 +498,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUint8 = new([]uint8) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint8, input, "PtrArrayUint8") + j.PtrArrayUint8, err = utils.DecodeNullableObjectValue[[]uint8](input, "PtrArrayUint8") if err != nil { return err } @@ -557,12 +526,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Text, input, "Text") + j.Text, err = utils.DecodeObjectValue[Text](input, "Text") if err != nil { return err } - j.TextPtr = new(Text) - err = connector_Decoder.DecodeNullableObjectValue(j.TextPtr, input, "TextPtr") + j.TextPtr, err = utils.DecodeNullableObjectValue[Text](input, "TextPtr") if err != nil { return err } @@ -574,7 +542,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.URL, input, "URL") + j.URL, err = utils.DecodeObjectValue[scalar.URL](input, "URL") if err != nil { return err } @@ -630,11 +598,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.ArrayBigIntEmpty, input, "array_bigint_empty") + j.ArrayBigIntEmpty, err = utils.DecodeObjectValueDefault[[]scalar.BigInt](input, "array_bigint_empty") if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.ArrayBigIntPtrEmpty, input, "array_bigint_ptr_empty") + j.ArrayBigIntPtrEmpty, err = utils.DecodeObjectValueDefault[[]*scalar.BigInt](input, "array_bigint_ptr_empty") if err != nil { return err } @@ -782,7 +750,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.BigIntEmpty, input, "bigint_empty") + j.BigIntEmpty, err = utils.DecodeObjectValueDefault[scalar.BigInt](input, "bigint_empty") if err != nil { return err } @@ -790,7 +758,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.DateEmpty, input, "date_empty") + j.DateEmpty, err = utils.DecodeObjectValueDefault[scalar.Date](input, "date_empty") if err != nil { return err } @@ -850,7 +818,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.URLEmpty, input, "url_empty") + j.URLEmpty, err = utils.DecodeObjectValueDefault[scalar.URL](input, "url_empty") if err != nil { return err } @@ -1269,8 +1237,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat "cause": err.Error(), }) } - var args GetCustomHeadersArguments[BaseAuthor, int] - if parseErr := connector_Decoder.DecodeObject(&args, rawArgs); parseErr != nil { + args, parseErr := utils.DecodeObject[GetCustomHeadersArguments[BaseAuthor, int]](rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) @@ -1303,7 +1271,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat }) } var args GetTypesArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { + parseErr := args.FromValue(rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) @@ -1365,7 +1334,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat }) } var args GetArticlesArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { + parseErr := args.FromValue(rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) diff --git a/cmd/hasura-ndc-go/command/internal/testdata/snake_case/expected/functions.go.tmpl b/cmd/hasura-ndc-go/command/internal/testdata/snake_case/expected/functions.go.tmpl index e229d0b..78fbaff 100644 --- a/cmd/hasura-ndc-go/command/internal/testdata/snake_case/expected/functions.go.tmpl +++ b/cmd/hasura-ndc-go/command/internal/testdata/snake_case/expected/functions.go.tmpl @@ -15,608 +15,576 @@ import ( "slices" "time" ) -var connector_Decoder = utils.NewDecoder() // FromValue decodes values from map func (j *Author) FromValue(input map[string]any) error { var err error j.CreatedAt, err = utils.GetDateTime(input, "created_at") - if err != nil { - return err - } + if err != nil { + return err + } j.ID, err = utils.GetString(input, "id") - if err != nil { - return err - } + if err != nil { + return err + } return nil } // FromValue decodes values from map func (j *GetArticlesArguments) FromValue(input map[string]any) error { var err error j.Limit, err = utils.GetFloat[float64](input, "Limit") - if err != nil { - return err - } + if err != nil { + return err + } return nil } // FromValue decodes values from map func (j *GetTypesArguments) FromValue(input map[string]any) error { var err error - err = connector_Decoder.DecodeObjectValue(&j.ArrayBigInt, input, "ArrayBigInt") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.ArrayBigIntPtr, input, "ArrayBigIntPtr") - if err != nil { - return err - } + j.ArrayBigInt, err = utils.DecodeObjectValue[[]scalar.BigInt](input, "ArrayBigInt") + if err != nil { + return err + } + j.ArrayBigIntPtr, err = utils.DecodeObjectValue[[]*scalar.BigInt](input, "ArrayBigIntPtr") + if err != nil { + return err + } j.ArrayBool, err = utils.GetBooleanSlice(input, "ArrayBool") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayBoolPtr, err = utils.GetBooleanPtrSlice(input, "ArrayBoolPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayFloat32, err = utils.GetFloatSlice[float32](input, "ArrayFloat32") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayFloat32Ptr, err = utils.GetFloatPtrSlice[float32](input, "ArrayFloat32Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayFloat64, err = utils.GetFloatSlice[float64](input, "ArrayFloat64") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayFloat64Ptr, err = utils.GetFloatPtrSlice[float64](input, "ArrayFloat64Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt, err = utils.GetIntSlice[int](input, "ArrayInt") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt16, err = utils.GetIntSlice[int16](input, "ArrayInt16") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt16Ptr, err = utils.GetIntPtrSlice[int16](input, "ArrayInt16Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt32, err = utils.GetIntSlice[int32](input, "ArrayInt32") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt32Ptr, err = utils.GetIntPtrSlice[int32](input, "ArrayInt32Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt64, err = utils.GetIntSlice[int64](input, "ArrayInt64") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt64Ptr, err = utils.GetIntPtrSlice[int64](input, "ArrayInt64Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt8, err = utils.GetIntSlice[int8](input, "ArrayInt8") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayInt8Ptr, err = utils.GetIntPtrSlice[int8](input, "ArrayInt8Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayIntPtr, err = utils.GetIntPtrSlice[int](input, "ArrayIntPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayJSON, err = utils.GetArbitraryJSONSlice(input, "ArrayJSON") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayJSONPtr, err = utils.GetArbitraryJSONPtrSlice(input, "ArrayJSONPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.ArrayMap, input, "ArrayMap") - if err != nil { - return err - } - j.ArrayMapPtr = new([]map[string]any) - err = connector_Decoder.DecodeNullableObjectValue(j.ArrayMapPtr, input, "ArrayMapPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.ArrayObject, input, "ArrayObject") - if err != nil { - return err - } - j.ArrayObjectPtr = new([]struct{Content string "json:\"content\""}) - err = connector_Decoder.DecodeNullableObjectValue(j.ArrayObjectPtr, input, "ArrayObjectPtr") - if err != nil { - return err - } + if err != nil { + return err + } + j.ArrayMap, err = utils.DecodeObjectValue[[]map[string]any](input, "ArrayMap") + if err != nil { + return err + } + j.ArrayMapPtr, err = utils.DecodeNullableObjectValue[[]map[string]any](input, "ArrayMapPtr") + if err != nil { + return err + } + j.ArrayObject, err = utils.DecodeObjectValue[[]struct{Content string `json:"content"`}](input, "ArrayObject") + if err != nil { + return err + } + j.ArrayObjectPtr, err = utils.DecodeNullableObjectValue[[]struct{Content string `json:"content"`}](input, "ArrayObjectPtr") + if err != nil { + return err + } j.ArrayRawJSON, err = utils.GetRawJSONSlice(input, "ArrayRawJSON") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayRawJSONPtr, err = utils.GetRawJSONPtrSlice(input, "ArrayRawJSONPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayString, err = utils.GetStringSlice(input, "ArrayString") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayStringPtr, err = utils.GetStringPtrSlice(input, "ArrayStringPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayTime, err = utils.GetDateTimeSlice(input, "ArrayTime") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayTimePtr, err = utils.GetDateTimePtrSlice(input, "ArrayTimePtr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUUID, err = utils.GetUUIDSlice(input, "ArrayUUID") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUUIDPtr, err = utils.GetUUIDPtrSlice(input, "ArrayUUIDPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint, err = utils.GetUintSlice[uint](input, "ArrayUint") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint16, err = utils.GetUintSlice[uint16](input, "ArrayUint16") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint16Ptr, err = utils.GetUintPtrSlice[uint16](input, "ArrayUint16Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint32, err = utils.GetUintSlice[uint32](input, "ArrayUint32") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint32Ptr, err = utils.GetUintPtrSlice[uint32](input, "ArrayUint32Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint64, err = utils.GetUintSlice[uint64](input, "ArrayUint64") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint64Ptr, err = utils.GetUintPtrSlice[uint64](input, "ArrayUint64Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint8, err = utils.GetUintSlice[uint8](input, "ArrayUint8") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUint8Ptr, err = utils.GetUintPtrSlice[uint8](input, "ArrayUint8Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.ArrayUintPtr, err = utils.GetUintPtrSlice[uint](input, "ArrayUintPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.BigInt, input, "BigInt") - if err != nil { - return err - } - j.BigIntPtr = new(scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.BigIntPtr, input, "BigIntPtr") - if err != nil { - return err - } + if err != nil { + return err + } + j.BigInt, err = utils.DecodeObjectValue[scalar.BigInt](input, "BigInt") + if err != nil { + return err + } + j.BigIntPtr, err = utils.DecodeNullableObjectValue[scalar.BigInt](input, "BigIntPtr") + if err != nil { + return err + } j.Bool, err = utils.GetBoolean(input, "Bool") - if err != nil { - return err - } + if err != nil { + return err + } j.BoolPtr, err = utils.GetNullableBoolean(input, "BoolPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.Bytes, input, "Bytes") - if err != nil { - return err - } - j.BytesPtr = new(scalar.Bytes) - err = connector_Decoder.DecodeNullableObjectValue(j.BytesPtr, input, "BytesPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.CustomScalar, input, "CustomScalar") - if err != nil { - return err - } - j.CustomScalarPtr = new(CommentText) - err = connector_Decoder.DecodeNullableObjectValue(j.CustomScalarPtr, input, "CustomScalarPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.Enum, input, "Enum") - if err != nil { - return err - } - j.EnumPtr = new(SomeEnum) - err = connector_Decoder.DecodeNullableObjectValue(j.EnumPtr, input, "EnumPtr") - if err != nil { - return err - } + if err != nil { + return err + } + j.Bytes, err = utils.DecodeObjectValue[scalar.Bytes](input, "Bytes") + if err != nil { + return err + } + j.BytesPtr, err = utils.DecodeNullableObjectValue[scalar.Bytes](input, "BytesPtr") + if err != nil { + return err + } + j.CustomScalar, err = utils.DecodeObjectValue[CommentText](input, "CustomScalar") + if err != nil { + return err + } + j.CustomScalarPtr, err = utils.DecodeNullableObjectValue[CommentText](input, "CustomScalarPtr") + if err != nil { + return err + } + j.Enum, err = utils.DecodeObjectValue[SomeEnum](input, "Enum") + if err != nil { + return err + } + j.EnumPtr, err = utils.DecodeNullableObjectValue[SomeEnum](input, "EnumPtr") + if err != nil { + return err + } j.Float32, err = utils.GetFloat[float32](input, "Float32") - if err != nil { - return err - } + if err != nil { + return err + } j.Float32Ptr, err = utils.GetNullableFloat[float32](input, "Float32Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.Float64, err = utils.GetFloat[float64](input, "Float64") - if err != nil { - return err - } + if err != nil { + return err + } j.Float64Ptr, err = utils.GetNullableFloat[float64](input, "Float64Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.Int, err = utils.GetInt[int](input, "Int") - if err != nil { - return err - } + if err != nil { + return err + } j.Int16, err = utils.GetInt[int16](input, "Int16") - if err != nil { - return err - } + if err != nil { + return err + } j.Int16Ptr, err = utils.GetNullableInt[int16](input, "Int16Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.Int32, err = utils.GetInt[int32](input, "Int32") - if err != nil { - return err - } + if err != nil { + return err + } j.Int32Ptr, err = utils.GetNullableInt[int32](input, "Int32Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.Int64, err = utils.GetInt[int64](input, "Int64") - if err != nil { - return err - } + if err != nil { + return err + } j.Int64Ptr, err = utils.GetNullableInt[int64](input, "Int64Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.Int8, err = utils.GetInt[int8](input, "Int8") - if err != nil { - return err - } + if err != nil { + return err + } j.Int8Ptr, err = utils.GetNullableInt[int8](input, "Int8Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.IntPtr, err = utils.GetNullableInt[int](input, "IntPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.JSON, err = utils.GetArbitraryJSON(input, "JSON") - if err != nil { - return err - } + if err != nil { + return err + } j.JSONPtr, err = utils.GetNullableArbitraryJSON(input, "JSONPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.Map, input, "Map") - if err != nil { - return err - } - j.MapPtr = new(map[string]any) - err = connector_Decoder.DecodeNullableObjectValue(j.MapPtr, input, "MapPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.NamedArray, input, "NamedArray") - if err != nil { - return err - } - j.NamedArrayPtr = new([]Author) - err = connector_Decoder.DecodeNullableObjectValue(j.NamedArrayPtr, input, "NamedArrayPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.NamedObject, input, "NamedObject") - if err != nil { - return err - } - j.NamedObjectPtr = new(Author) - err = connector_Decoder.DecodeNullableObjectValue(j.NamedObjectPtr, input, "NamedObjectPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.Object, input, "Object") - if err != nil { - return err - } - j.ObjectPtr = new(struct{Long int; Lat int}) - err = connector_Decoder.DecodeNullableObjectValue(j.ObjectPtr, input, "ObjectPtr") - if err != nil { - return err - } - j.PtrArrayBigInt = new([]scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBigInt, input, "PtrArrayBigInt") - if err != nil { - return err - } - j.PtrArrayBigIntPtr = new([]*scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBigIntPtr, input, "PtrArrayBigIntPtr") - if err != nil { - return err - } - j.PtrArrayBool = new([]bool) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBool, input, "PtrArrayBool") - if err != nil { - return err - } + if err != nil { + return err + } + j.Map, err = utils.DecodeObjectValue[map[string]any](input, "Map") + if err != nil { + return err + } + j.MapPtr, err = utils.DecodeNullableObjectValue[map[string]any](input, "MapPtr") + if err != nil { + return err + } + j.NamedArray, err = utils.DecodeObjectValue[[]Author](input, "NamedArray") + if err != nil { + return err + } + j.NamedArrayPtr, err = utils.DecodeNullableObjectValue[[]Author](input, "NamedArrayPtr") + if err != nil { + return err + } + j.NamedObject, err = utils.DecodeObjectValue[Author](input, "NamedObject") + if err != nil { + return err + } + j.NamedObjectPtr, err = utils.DecodeNullableObjectValue[Author](input, "NamedObjectPtr") + if err != nil { + return err + } + j.Object, err = utils.DecodeObjectValue[struct{ID uuid.UUID `json:"id"`; CreatedAt time.Time `json:"created_at"`}](input, "Object") + if err != nil { + return err + } + j.ObjectPtr, err = utils.DecodeNullableObjectValue[struct{Long int; Lat int}](input, "ObjectPtr") + if err != nil { + return err + } + j.PtrArrayBigInt, err = utils.DecodeNullableObjectValue[[]scalar.BigInt](input, "PtrArrayBigInt") + if err != nil { + return err + } + j.PtrArrayBigIntPtr, err = utils.DecodeNullableObjectValue[[]*scalar.BigInt](input, "PtrArrayBigIntPtr") + if err != nil { + return err + } + j.PtrArrayBool, err = utils.DecodeNullableObjectValue[[]bool](input, "PtrArrayBool") + if err != nil { + return err + } j.PtrArrayBoolPtr, err = utils.GetNullableBooleanPtrSlice(input, "PtrArrayBoolPtr") - if err != nil { - return err - } - j.PtrArrayFloat32 = new([]float32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayFloat32, input, "PtrArrayFloat32") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayFloat32, err = utils.DecodeNullableObjectValue[[]float32](input, "PtrArrayFloat32") + if err != nil { + return err + } j.PtrArrayFloat32Ptr, err = utils.GetNullableFloatPtrSlice[float32](input, "PtrArrayFloat32Ptr") - if err != nil { - return err - } - j.PtrArrayFloat64 = new([]float64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayFloat64, input, "PtrArrayFloat64") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayFloat64, err = utils.DecodeNullableObjectValue[[]float64](input, "PtrArrayFloat64") + if err != nil { + return err + } j.PtrArrayFloat64Ptr, err = utils.GetNullableFloatPtrSlice[float64](input, "PtrArrayFloat64Ptr") - if err != nil { - return err - } - j.PtrArrayInt = new([]int) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt, input, "PtrArrayInt") - if err != nil { - return err - } - j.PtrArrayInt16 = new([]int16) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt16, input, "PtrArrayInt16") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayInt, err = utils.DecodeNullableObjectValue[[]int](input, "PtrArrayInt") + if err != nil { + return err + } + j.PtrArrayInt16, err = utils.DecodeNullableObjectValue[[]int16](input, "PtrArrayInt16") + if err != nil { + return err + } j.PtrArrayInt16Ptr, err = utils.GetNullableIntPtrSlice[int16](input, "PtrArrayInt16Ptr") - if err != nil { - return err - } - j.PtrArrayInt32 = new([]int32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt32, input, "PtrArrayInt32") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayInt32, err = utils.DecodeNullableObjectValue[[]int32](input, "PtrArrayInt32") + if err != nil { + return err + } j.PtrArrayInt32Ptr, err = utils.GetNullableIntPtrSlice[int32](input, "PtrArrayInt32Ptr") - if err != nil { - return err - } - j.PtrArrayInt64 = new([]int64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt64, input, "PtrArrayInt64") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayInt64, err = utils.DecodeNullableObjectValue[[]int64](input, "PtrArrayInt64") + if err != nil { + return err + } j.PtrArrayInt64Ptr, err = utils.GetNullableIntPtrSlice[int64](input, "PtrArrayInt64Ptr") - if err != nil { - return err - } - j.PtrArrayInt8 = new([]int8) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt8, input, "PtrArrayInt8") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayInt8, err = utils.DecodeNullableObjectValue[[]int8](input, "PtrArrayInt8") + if err != nil { + return err + } j.PtrArrayInt8Ptr, err = utils.GetNullableIntPtrSlice[int8](input, "PtrArrayInt8Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.PtrArrayIntPtr, err = utils.GetNullableIntPtrSlice[int](input, "PtrArrayIntPtr") - if err != nil { - return err - } - j.PtrArrayJSON = new([]any) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayJSON, input, "PtrArrayJSON") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayJSON, err = utils.DecodeNullableObjectValue[[]any](input, "PtrArrayJSON") + if err != nil { + return err + } j.PtrArrayJSONPtr, err = utils.GetNullableArbitraryJSONPtrSlice(input, "PtrArrayJSONPtr") - if err != nil { - return err - } - j.PtrArrayRawJSON = new([]json.RawMessage) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayRawJSON, input, "PtrArrayRawJSON") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayRawJSON, err = utils.DecodeNullableObjectValue[[]json.RawMessage](input, "PtrArrayRawJSON") + if err != nil { + return err + } j.PtrArrayRawJSONPtr, err = utils.GetNullableRawJSONPtrSlice(input, "PtrArrayRawJSONPtr") - if err != nil { - return err - } - j.PtrArrayString = new([]string) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayString, input, "PtrArrayString") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayString, err = utils.DecodeNullableObjectValue[[]string](input, "PtrArrayString") + if err != nil { + return err + } j.PtrArrayStringPtr, err = utils.GetNullableStringPtrSlice(input, "PtrArrayStringPtr") - if err != nil { - return err - } - j.PtrArrayTime = new([]time.Time) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayTime, input, "PtrArrayTime") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayTime, err = utils.DecodeNullableObjectValue[[]time.Time](input, "PtrArrayTime") + if err != nil { + return err + } j.PtrArrayTimePtr, err = utils.GetNullableDateTimePtrSlice(input, "PtrArrayTimePtr") - if err != nil { - return err - } - j.PtrArrayUUID = new([]uuid.UUID) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUUID, input, "PtrArrayUUID") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayUUID, err = utils.DecodeNullableObjectValue[[]uuid.UUID](input, "PtrArrayUUID") + if err != nil { + return err + } j.PtrArrayUUIDPtr, err = utils.GetNullableUUIDPtrSlice(input, "PtrArrayUUIDPtr") - if err != nil { - return err - } - j.PtrArrayUint = new([]uint) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint, input, "PtrArrayUint") - if err != nil { - return err - } - j.PtrArrayUint16 = new([]uint16) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint16, input, "PtrArrayUint16") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayUint, err = utils.DecodeNullableObjectValue[[]uint](input, "PtrArrayUint") + if err != nil { + return err + } + j.PtrArrayUint16, err = utils.DecodeNullableObjectValue[[]uint16](input, "PtrArrayUint16") + if err != nil { + return err + } j.PtrArrayUint16Ptr, err = utils.GetNullableUintPtrSlice[uint16](input, "PtrArrayUint16Ptr") - if err != nil { - return err - } - j.PtrArrayUint32 = new([]uint32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint32, input, "PtrArrayUint32") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayUint32, err = utils.DecodeNullableObjectValue[[]uint32](input, "PtrArrayUint32") + if err != nil { + return err + } j.PtrArrayUint32Ptr, err = utils.GetNullableUintPtrSlice[uint32](input, "PtrArrayUint32Ptr") - if err != nil { - return err - } - j.PtrArrayUint64 = new([]uint64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint64, input, "PtrArrayUint64") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayUint64, err = utils.DecodeNullableObjectValue[[]uint64](input, "PtrArrayUint64") + if err != nil { + return err + } j.PtrArrayUint64Ptr, err = utils.GetNullableUintPtrSlice[uint64](input, "PtrArrayUint64Ptr") - if err != nil { - return err - } - j.PtrArrayUint8 = new([]uint8) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint8, input, "PtrArrayUint8") - if err != nil { - return err - } + if err != nil { + return err + } + j.PtrArrayUint8, err = utils.DecodeNullableObjectValue[[]uint8](input, "PtrArrayUint8") + if err != nil { + return err + } j.PtrArrayUint8Ptr, err = utils.GetNullableUintPtrSlice[uint8](input, "PtrArrayUint8Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.PtrArrayUintPtr, err = utils.GetNullableUintPtrSlice[uint](input, "PtrArrayUintPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.RawJSON, err = utils.GetRawJSON(input, "RawJSON") - if err != nil { - return err - } + if err != nil { + return err + } j.RawJSONPtr, err = utils.GetNullableRawJSON(input, "RawJSONPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.String, err = utils.GetString(input, "String") - if err != nil { - return err - } + if err != nil { + return err + } j.StringPtr, err = utils.GetNullableString(input, "StringPtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.Text, input, "Text") - if err != nil { - return err - } - j.TextPtr = new(Text) - err = connector_Decoder.DecodeNullableObjectValue(j.TextPtr, input, "TextPtr") - if err != nil { - return err - } + if err != nil { + return err + } + j.Text, err = utils.DecodeObjectValue[Text](input, "Text") + if err != nil { + return err + } + j.TextPtr, err = utils.DecodeNullableObjectValue[Text](input, "TextPtr") + if err != nil { + return err + } j.Time, err = utils.GetDateTime(input, "Time") - if err != nil { - return err - } + if err != nil { + return err + } j.TimePtr, err = utils.GetNullableDateTime(input, "TimePtr") - if err != nil { - return err - } - err = connector_Decoder.DecodeObjectValue(&j.URL, input, "URL") - if err != nil { - return err - } + if err != nil { + return err + } + j.URL, err = utils.DecodeObjectValue[scalar.URL](input, "URL") + if err != nil { + return err + } j.UUID, err = utils.GetUUID(input, "UUID") - if err != nil { - return err - } + if err != nil { + return err + } j.UUIDArray, err = utils.GetUUIDSlice(input, "UUIDArray") - if err != nil { - return err - } + if err != nil { + return err + } j.UUIDPtr, err = utils.GetNullableUUID(input, "UUIDPtr") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint, err = utils.GetUint[uint](input, "Uint") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint16, err = utils.GetUint[uint16](input, "Uint16") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint16Ptr, err = utils.GetNullableUint[uint16](input, "Uint16Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint32, err = utils.GetUint[uint32](input, "Uint32") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint32Ptr, err = utils.GetNullableUint[uint32](input, "Uint32Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint64, err = utils.GetUint[uint64](input, "Uint64") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint64Ptr, err = utils.GetNullableUint[uint64](input, "Uint64Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint8, err = utils.GetUint[uint8](input, "Uint8") - if err != nil { - return err - } + if err != nil { + return err + } j.Uint8Ptr, err = utils.GetNullableUint[uint8](input, "Uint8Ptr") - if err != nil { - return err - } + if err != nil { + return err + } j.UintPtr, err = utils.GetNullableUint[uint](input, "UintPtr") - if err != nil { - return err - } + if err != nil { + return err + } return nil } // ToMap encodes the struct to a value map @@ -625,7 +593,7 @@ func (j Author) ToMap() map[string]any { r["created_at"] = j.CreatedAt r["id"] = j.ID - return r + return r } // ToMap encodes the struct to a value map func (j CreateArticleResult) ToMap() map[string]any { @@ -637,7 +605,7 @@ func (j CreateArticleResult) ToMap() map[string]any { r["authors"] = j_Authors r["id"] = j.ID - return r + return r } // ToMap encodes the struct to a value map func (j CreateAuthorResult) ToMap() map[string]any { @@ -646,7 +614,7 @@ func (j CreateAuthorResult) ToMap() map[string]any { r["id"] = j.ID r["name"] = j.Name - return r + return r } // ToMap encodes the struct to a value map func (j GetArticlesResult) ToMap() map[string]any { @@ -654,7 +622,7 @@ func (j GetArticlesResult) ToMap() map[string]any { r["Name"] = j.Name r["id"] = j.ID - return r + return r } // ToMap encodes the struct to a value map func (j GetTypesArguments) ToMap() map[string]any { @@ -830,7 +798,7 @@ func (j GetTypesArguments) ToMap() map[string]any { r["Uint8Ptr"] = j.Uint8Ptr r["UintPtr"] = j.UintPtr - return r + return r } // ToMap encodes the struct to a value map func (j HelloResult) ToMap() map[string]any { @@ -841,7 +809,7 @@ func (j HelloResult) ToMap() map[string]any { r["num"] = j.Num r["text"] = j.Text - return r + return r } // ScalarName get the schema name of the scalar func (j CommentText) ScalarName() string { @@ -866,51 +834,51 @@ var enumValues_SomeEnum = []SomeEnum{SomeEnumFoo, SomeEnumBar} // ParseSomeEnum parses a SomeEnum enum from string func ParseSomeEnum(input string) (SomeEnum, error) { - result := SomeEnum(input) - if !slices.Contains(enumValues_SomeEnum, result) { - return SomeEnum(""), errors.New("failed to parse SomeEnum, expect one of SomeEnumFoo, SomeEnumBar") - } + result := SomeEnum(input) + if !slices.Contains(enumValues_SomeEnum, result) { + return SomeEnum(""), errors.New("failed to parse SomeEnum, expect one of SomeEnumFoo, SomeEnumBar") + } - return result, nil + return result, nil } // IsValid checks if the value is invalid func (j SomeEnum) IsValid() bool { - return slices.Contains(enumValues_SomeEnum, j) + return slices.Contains(enumValues_SomeEnum, j) } // UnmarshalJSON implements json.Unmarshaler. func (j *SomeEnum) UnmarshalJSON(b []byte) error { - var rawValue string - if err := json.Unmarshal(b, &rawValue); err != nil { - return err - } + var rawValue string + if err := json.Unmarshal(b, &rawValue); err != nil { + return err + } - value, err := ParseSomeEnum(rawValue) - if err != nil { - return err - } + value, err := ParseSomeEnum(rawValue) + if err != nil { + return err + } - *j = value - return nil + *j = value + return nil } // FromValue decodes the scalar from an unknown value func (s *SomeEnum) FromValue(value any) error { - valueStr, err := utils.DecodeNullableString(value) - if err != nil { - return err - } - if valueStr == nil { - return nil - } - result, err := ParseSomeEnum(*valueStr) - if err != nil { - return err - } + valueStr, err := utils.DecodeNullableString(value) + if err != nil { + return err + } + if valueStr == nil { + return nil + } + result, err := ParseSomeEnum(*valueStr) + if err != nil { + return err + } - *s = result - return nil + *s = result + return nil } // DataConnectorHandler implements the data connector handler @@ -918,62 +886,64 @@ type DataConnectorHandler struct{} // QueryExists check if the query name exists func (dch DataConnectorHandler) QueryExists(name string) bool { - return slices.Contains(enumValues_FunctionName, name) + return slices.Contains(enumValues_FunctionName, name) } func (dch DataConnectorHandler) Query(ctx context.Context, state *types.State, request *schema.QueryRequest, rawArgs map[string]any) (*schema.RowSet, error) { - if !dch.QueryExists(request.Collection) { - return nil, utils.ErrHandlerNotfound - } - queryFields, err := utils.EvalFunctionSelectionFieldValue(request) - if err != nil { - return nil, schema.UnprocessableContentError(err.Error(), nil) - } + if !dch.QueryExists(request.Collection) { + return nil, utils.ErrHandlerNotfound + } + queryFields, err := utils.EvalFunctionSelectionFieldValue(request) + if err != nil { + return nil, schema.UnprocessableContentError(err.Error(), nil) + } - result, err := dch.execQuery(ctx, state, request, queryFields, rawArgs) - if err != nil { - return nil, err - } - - return &schema.RowSet{ - Aggregates: schema.RowSetAggregates{}, - Rows: []map[string]any{ - { - "__value": result, - }, - }, - }, nil + result, err := dch.execQuery(ctx, state, request, queryFields, rawArgs) + if err != nil { + return nil, err + } + + return &schema.RowSet{ + Aggregates: schema.RowSetAggregates{}, + Rows: []map[string]any{ + { + "__value": result, + }, + }, + }, nil } - + func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.State, request *schema.QueryRequest, queryFields schema.NestedField, rawArgs map[string]any) (any, error) { - span := trace.SpanFromContext(ctx) - logger := connector.GetLogger(ctx) - switch request.Collection { + span := trace.SpanFromContext(ctx) + logger := connector.GetLogger(ctx) + switch request.Collection { case "get_bool": - if len(queryFields) > 0 { - return nil, schema.UnprocessableContentError("cannot evaluate selection fields for scalar", nil) - } + if len(queryFields) > 0 { + return nil, schema.UnprocessableContentError("cannot evaluate selection fields for scalar", nil) + } return FunctionGetBool(ctx, state) case "get_types": - selection, err := queryFields.AsObject() - if err != nil { - return nil, schema.UnprocessableContentError("the selection field type must be object", map[string]any{ - "cause": err.Error(), - }) - } - var args GetTypesArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { - return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ - "cause": parseErr.Error(), - }) - } - - connector_addSpanEvent(span, logger, "execute_function", map[string]any{ - "arguments": args, - }) + selection, err := queryFields.AsObject() + if err != nil { + return nil, schema.UnprocessableContentError("the selection field type must be object", map[string]any{ + "cause": err.Error(), + }) + } + var args GetTypesArguments + parseErr := args.FromValue(rawArgs) + if parseErr != nil { + return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ + "cause": parseErr.Error(), + }) + } + + connector_addSpanEvent(span, logger, "execute_function", map[string]any{ + "arguments": args, + }) rawResult, err := FunctionGetTypes(ctx, state, &args) + if err != nil { return nil, err } @@ -981,10 +951,9 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat if rawResult == nil { return nil, nil } - - connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ - "raw_result": rawResult, - }) + connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ + "raw_result": rawResult, + }) result, err := utils.EvalNestedColumnObject(selection, rawResult) if err != nil { return nil, err @@ -993,13 +962,14 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat case "hello": - selection, err := queryFields.AsObject() - if err != nil { - return nil, schema.UnprocessableContentError("the selection field type must be object", map[string]any{ - "cause": err.Error(), - }) - } + selection, err := queryFields.AsObject() + if err != nil { + return nil, schema.UnprocessableContentError("the selection field type must be object", map[string]any{ + "cause": err.Error(), + }) + } rawResult, err := FunctionHello(ctx, state) + if err != nil { return nil, err } @@ -1007,10 +977,9 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat if rawResult == nil { return nil, nil } - - connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ - "raw_result": rawResult, - }) + connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ + "raw_result": rawResult, + }) result, err := utils.EvalNestedColumnObject(selection, rawResult) if err != nil { return nil, err @@ -1019,53 +988,55 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat case "get_articles": - selection, err := queryFields.AsArray() - if err != nil { - return nil, schema.UnprocessableContentError("the selection field type must be array", map[string]any{ - "cause": err.Error(), - }) - } - var args GetArticlesArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { - return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ - "cause": parseErr.Error(), - }) - } - - connector_addSpanEvent(span, logger, "execute_function", map[string]any{ - "arguments": args, - }) + selection, err := queryFields.AsArray() + if err != nil { + return nil, schema.UnprocessableContentError("the selection field type must be array", map[string]any{ + "cause": err.Error(), + }) + } + var args GetArticlesArguments + parseErr := args.FromValue(rawArgs) + if parseErr != nil { + return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ + "cause": parseErr.Error(), + }) + } + + connector_addSpanEvent(span, logger, "execute_function", map[string]any{ + "arguments": args, + }) rawResult, err := GetArticles(ctx, state, &args) + if err != nil { return nil, err } - connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ - "raw_result": rawResult, - }) + connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ + "raw_result": rawResult, + }) result, err := utils.EvalNestedColumnArrayIntoSlice(selection, rawResult) if err != nil { return nil, err } return result, nil - default: - return nil, utils.ErrHandlerNotfound - } + default: + return nil, utils.ErrHandlerNotfound + } } var enumValues_FunctionName = []string{"get_bool", "get_types", "hello", "get_articles"} // MutationExists check if the mutation name exists func (dch DataConnectorHandler) MutationExists(name string) bool { - return slices.Contains(enumValues_ProcedureName, name) + return slices.Contains(enumValues_ProcedureName, name) } func (dch DataConnectorHandler) Mutation(ctx context.Context, state *types.State, operation *schema.MutationOperation) (schema.MutationOperationResults, error) { - span := trace.SpanFromContext(ctx) - logger := connector.GetLogger(ctx) - connector_addSpanEvent(span, logger, "validate_request", map[string]any{ - "operations_name": operation.Name, - }) - - switch operation.Name { + span := trace.SpanFromContext(ctx) + logger := connector.GetLogger(ctx) + connector_addSpanEvent(span, logger, "validate_request", map[string]any{ + "operations_name": operation.Name, + }) + + switch operation.Name { case "create_article": selection, err := operation.Fields.AsObject() @@ -1091,8 +1062,8 @@ func (dch DataConnectorHandler) Mutation(ctx context.Context, state *types.State return schema.NewProcedureResult(nil).Encode(), nil } connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ - "raw_result": rawResult, - }) + "raw_result": rawResult, + }) result, err := utils.EvalNestedColumnObject(selection, rawResult) if err != nil { @@ -1102,11 +1073,12 @@ func (dch DataConnectorHandler) Mutation(ctx context.Context, state *types.State case "increase": - if len(operation.Fields) > 0 { - return nil, schema.UnprocessableContentError("cannot evaluate selection fields for scalar", nil) - } + if len(operation.Fields) > 0 { + return nil, schema.UnprocessableContentError("cannot evaluate selection fields for scalar", nil) + } span.AddEvent("execute_procedure") result, err := Increase(ctx, state) + if err != nil { return nil, err } @@ -1137,8 +1109,8 @@ func (dch DataConnectorHandler) Mutation(ctx context.Context, state *types.State return schema.NewProcedureResult(nil).Encode(), nil } connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ - "raw_result": rawResult, - }) + "raw_result": rawResult, + }) result, err := utils.EvalNestedColumnObject(selection, rawResult) if err != nil { @@ -1166,9 +1138,10 @@ func (dch DataConnectorHandler) Mutation(ctx context.Context, state *types.State if err != nil { return nil, err } + connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ - "raw_result": rawResult, - }) + "raw_result": rawResult, + }) result, err := utils.EvalNestedColumnArrayIntoSlice(selection, rawResult) if err != nil { @@ -1176,13 +1149,13 @@ func (dch DataConnectorHandler) Mutation(ctx context.Context, state *types.State } return schema.NewProcedureResult(result).Encode(), nil - default: - return nil, utils.ErrHandlerNotfound - } + default: + return nil, utils.ErrHandlerNotfound + } } -var enumValues_ProcedureName = []string{"create_article", "increase", "create_author", "create_authors"} +var enumValues_ProcedureName = []string{"create_article", "increase", "create_author", "create_authors"} func connector_addSpanEvent(span trace.Span, logger *slog.Logger, name string, data map[string]any, options ...trace.EventOption) { - logger.Debug(name, slog.Any("data", data)) - attrs := utils.DebugJSONAttributes(data, utils.IsDebug(logger)) - span.AddEvent(name, append(options, trace.WithAttributes(attrs...))...) + logger.Debug(name, slog.Any("data", data)) + attrs := utils.DebugJSONAttributes(data, utils.IsDebug(logger)) + span.AddEvent(name, append(options, trace.WithAttributes(attrs...))...) } \ No newline at end of file diff --git a/cmd/hasura-ndc-go/command/internal/testdata/subdir/expected/functions.go.tmpl b/cmd/hasura-ndc-go/command/internal/testdata/subdir/expected/functions.go.tmpl index b7bb228..0c0b0c0 100644 --- a/cmd/hasura-ndc-go/command/internal/testdata/subdir/expected/functions.go.tmpl +++ b/cmd/hasura-ndc-go/command/internal/testdata/subdir/expected/functions.go.tmpl @@ -2,6 +2,7 @@ package functions import ( "context" + "github.com/hasura/ndc-codegen-example/types" "github.com/hasura/ndc-codegen-subdir-test/connector/types" "github.com/hasura/ndc-sdk-go/connector" "github.com/hasura/ndc-sdk-go/schema" @@ -10,19 +11,18 @@ import ( "log/slog" "slices" ) -var connector_Decoder = utils.NewDecoder() // FromValue decodes values from map func (j *GetArticlesArguments) FromValue(input map[string]any) error { var err error - err = connector_Decoder.DecodeObject(&j.Author, input) - if err != nil { - return err - } + j.Author, err = utils.DecodeObject[types.Author](input) + if err != nil { + return err + } j.Limit, err = utils.GetFloat[float64](input, "Limit") - if err != nil { - return err - } + if err != nil { + return err + } return nil } // ToMap encodes the struct to a value map @@ -31,82 +31,84 @@ func (j GetArticlesResult) ToMap() map[string]any { r = utils.MergeMap(r, j.Author.ToMap()) r["id"] = j.ID - return r + return r } // DataConnectorHandler implements the data connector handler type DataConnectorHandler struct{} // QueryExists check if the query name exists func (dch DataConnectorHandler) QueryExists(name string) bool { - return slices.Contains(enumValues_FunctionName, name) + return slices.Contains(enumValues_FunctionName, name) } func (dch DataConnectorHandler) Query(ctx context.Context, state *types.State, request *schema.QueryRequest, rawArgs map[string]any) (*schema.RowSet, error) { - if !dch.QueryExists(request.Collection) { - return nil, utils.ErrHandlerNotfound - } - queryFields, err := utils.EvalFunctionSelectionFieldValue(request) - if err != nil { - return nil, schema.UnprocessableContentError(err.Error(), nil) - } + if !dch.QueryExists(request.Collection) { + return nil, utils.ErrHandlerNotfound + } + queryFields, err := utils.EvalFunctionSelectionFieldValue(request) + if err != nil { + return nil, schema.UnprocessableContentError(err.Error(), nil) + } - result, err := dch.execQuery(ctx, state, request, queryFields, rawArgs) - if err != nil { - return nil, err - } - - return &schema.RowSet{ - Aggregates: schema.RowSetAggregates{}, - Rows: []map[string]any{ - { - "__value": result, - }, - }, - }, nil + result, err := dch.execQuery(ctx, state, request, queryFields, rawArgs) + if err != nil { + return nil, err + } + + return &schema.RowSet{ + Aggregates: schema.RowSetAggregates{}, + Rows: []map[string]any{ + { + "__value": result, + }, + }, + }, nil } - + func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.State, request *schema.QueryRequest, queryFields schema.NestedField, rawArgs map[string]any) (any, error) { - span := trace.SpanFromContext(ctx) - logger := connector.GetLogger(ctx) - switch request.Collection { + span := trace.SpanFromContext(ctx) + logger := connector.GetLogger(ctx) + switch request.Collection { case "getArticles": - selection, err := queryFields.AsArray() - if err != nil { - return nil, schema.UnprocessableContentError("the selection field type must be array", map[string]any{ - "cause": err.Error(), - }) - } - var args GetArticlesArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { - return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ - "cause": parseErr.Error(), - }) - } - - connector_addSpanEvent(span, logger, "execute_function", map[string]any{ - "arguments": args, - }) + selection, err := queryFields.AsArray() + if err != nil { + return nil, schema.UnprocessableContentError("the selection field type must be array", map[string]any{ + "cause": err.Error(), + }) + } + var args GetArticlesArguments + parseErr := args.FromValue(rawArgs) + if parseErr != nil { + return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ + "cause": parseErr.Error(), + }) + } + + connector_addSpanEvent(span, logger, "execute_function", map[string]any{ + "arguments": args, + }) rawResult, err := GetArticles(ctx, state, &args) + if err != nil { return nil, err } - connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ - "raw_result": rawResult, - }) + connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{ + "raw_result": rawResult, + }) result, err := utils.EvalNestedColumnArrayIntoSlice(selection, rawResult) if err != nil { return nil, err } return result, nil - default: - return nil, utils.ErrHandlerNotfound - } + default: + return nil, utils.ErrHandlerNotfound + } } -var enumValues_FunctionName = []string{"getArticles"} +var enumValues_FunctionName = []string{"getArticles"} func connector_addSpanEvent(span trace.Span, logger *slog.Logger, name string, data map[string]any, options ...trace.EventOption) { - logger.Debug(name, slog.Any("data", data)) - attrs := utils.DebugJSONAttributes(data, utils.IsDebug(logger)) - span.AddEvent(name, append(options, trace.WithAttributes(attrs...))...) + logger.Debug(name, slog.Any("data", data)) + attrs := utils.DebugJSONAttributes(data, utils.IsDebug(logger)) + span.AddEvent(name, append(options, trace.WithAttributes(attrs...))...) } \ No newline at end of file diff --git a/example/codegen/connector_test.go b/example/codegen/connector_test.go index 8c60794..e197bb5 100644 --- a/example/codegen/connector_test.go +++ b/example/codegen/connector_test.go @@ -1388,8 +1388,9 @@ func TestQueryGetTypes(t *testing.T) { BigIntPtr: utils.ToPtr(scalar.BigInt(20000)), DatePtr: scalar.NewDate(2024, 04, 03), Object: struct { - ID uuid.UUID `json:"id"` - CreatedAt time.Time `json:"created_at"` + ID uuid.UUID `json:"id"` + CreatedAt time.Time `json:"created_at"` + GenericField types.CustomHeadersResult[types.Author] `json:"generic_field,omitempty"` }{ ID: uuid.MustParse("b085b0b9-007c-440e-9661-0d8f2de98a5c"), CreatedAt: time.Date(2024, 3, 5, 6, 0, 0, 0, time.UTC), diff --git a/example/codegen/functions/types.generated.go b/example/codegen/functions/types.generated.go index 3ef3a8b..ec1d4cc 100644 --- a/example/codegen/functions/types.generated.go +++ b/example/codegen/functions/types.generated.go @@ -14,8 +14,6 @@ import ( "slices" ) -var connector_Decoder = utils.NewDecoder() - // FromValue decodes values from map func (j *BaseAuthor) FromValue(input map[string]any) error { var err error @@ -33,7 +31,7 @@ func (j *GetArticlesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObject(&j.BaseAuthor, input) + j.BaseAuthor, err = utils.DecodeObject[BaseAuthor](input) if err != nil { return err } @@ -47,8 +45,7 @@ func (j *GetArticlesArguments) FromValue(input map[string]any) error { // FromValue decodes values from map func (j *GetAuthorArguments) FromValue(input map[string]any) error { var err error - j.BaseAuthor = new(BaseAuthor) - err = connector_Decoder.DecodeObject(j.BaseAuthor, input) + j.BaseAuthor, err = utils.DecodeNullableObject[BaseAuthor](input) if err != nil { return err } @@ -179,7 +176,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat }) } var args GetAuthorArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { + parseErr := args.FromValue(rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) @@ -215,7 +213,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat }) } var args GetAuthorArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { + parseErr := args.FromValue(rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) @@ -254,8 +253,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat "cause": err.Error(), }) } - var args GetCustomHeadersArguments[BaseAuthor, int] - if parseErr := connector_Decoder.DecodeObject(&args, rawArgs); parseErr != nil { + args, parseErr := utils.DecodeObject[GetCustomHeadersArguments[BaseAuthor, int]](rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) @@ -287,8 +286,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat "cause": err.Error(), }) } - var args GetCustomHeadersArguments[arguments.GetCustomHeadersInput, int] - if parseErr := connector_Decoder.DecodeObject(&args, rawArgs); parseErr != nil { + args, parseErr := utils.DecodeObject[GetCustomHeadersArguments[arguments.GetCustomHeadersInput, int]](rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) @@ -321,7 +320,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat }) } var args arguments.GetTypesArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { + parseErr := args.FromValue(rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) @@ -383,7 +383,8 @@ func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.Stat }) } var args GetArticlesArguments - if parseErr := args.FromValue(rawArgs); parseErr != nil { + parseErr := args.FromValue(rawArgs) + if parseErr != nil { return nil, schema.UnprocessableContentError("failed to resolve arguments", map[string]any{ "cause": parseErr.Error(), }) diff --git a/example/codegen/schema.generated.go b/example/codegen/schema.generated.go index c0a74d4..d1fd4ac 100644 --- a/example/codegen/schema.generated.go +++ b/example/codegen/schema.generated.go @@ -80,6 +80,16 @@ func GetConnectorSchema() *schema.SchemaResponse { }, }, }, + "CustomHeadersResult_Author": schema.ObjectType{ + Fields: schema.ObjectTypeFields{ + "Response": schema.ObjectField{ + Type: schema.NewNamedType("Author").Encode(), + }, + "headers": schema.ObjectField{ + Type: schema.NewNullableType(schema.NewNamedType("JSON")).Encode(), + }, + }, + }, "CustomHeadersResult_array_nullable_BaseAuthor": schema.ObjectType{ Fields: schema.ObjectTypeFields{ "Response": schema.ObjectField{ @@ -782,6 +792,9 @@ func GetConnectorSchema() *schema.SchemaResponse { "created_at": schema.ObjectField{ Type: schema.NewNamedType("TimestampTZ").Encode(), }, + "generic_field": schema.ObjectField{ + Type: schema.NewNullableType(schema.NewNamedType("CustomHeadersResult_Author")).Encode(), + }, "id": schema.ObjectField{ Type: schema.NewNamedType("UUID").Encode(), }, diff --git a/example/codegen/types/arguments/arguments.go b/example/codegen/types/arguments/arguments.go index 8d75596..c8ec2d3 100644 --- a/example/codegen/types/arguments/arguments.go +++ b/example/codegen/types/arguments/arguments.go @@ -135,8 +135,9 @@ type GetTypesArguments struct { PtrArrayTimePtr *[]*time.Time Object struct { - ID uuid.UUID `json:"id"` - CreatedAt time.Time `json:"created_at"` + ID uuid.UUID `json:"id"` + CreatedAt time.Time `json:"created_at"` + GenericField types.CustomHeadersResult[types.Author] `json:"generic_field,omitempty"` } ObjectPtr *struct { Long int @@ -230,6 +231,9 @@ type GetTypesArguments struct { ArrayBigIntPtrEmpty []*scalar.BigInt `json:"array_bigint_ptr_empty,omitempty"` ArrayTimeEmpty []time.Time `json:"array_time_empty,omitempty"` ArrayTimePtrEmpty []*time.Time `json:"array_time_ptr_empty,omitempty"` + + privateField string + someFunc func() } type GetCustomHeadersInput struct { diff --git a/example/codegen/types/arguments/types.generated.go b/example/codegen/types/arguments/types.generated.go index 3096800..47bac7b 100644 --- a/example/codegen/types/arguments/types.generated.go +++ b/example/codegen/types/arguments/types.generated.go @@ -10,8 +10,6 @@ import ( "time" ) -var connector_Decoder = utils.NewDecoder() - // FromValue decodes values from map func (j *GetCustomHeadersInput) FromValue(input map[string]any) error { var err error @@ -29,11 +27,11 @@ func (j *GetCustomHeadersInput) FromValue(input map[string]any) error { // FromValue decodes values from map func (j *GetTypesArguments) FromValue(input map[string]any) error { var err error - err = connector_Decoder.DecodeObjectValue(&j.ArrayBigInt, input, "ArrayBigInt") + j.ArrayBigInt, err = utils.DecodeObjectValue[[]scalar.BigInt](input, "ArrayBigInt") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.ArrayBigIntPtr, input, "ArrayBigIntPtr") + j.ArrayBigIntPtr, err = utils.DecodeObjectValue[[]*scalar.BigInt](input, "ArrayBigIntPtr") if err != nil { return err } @@ -109,23 +107,23 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.ArrayMap, input, "ArrayMap") + j.ArrayMap, err = utils.DecodeObjectValue[[]map[string]any](input, "ArrayMap") if err != nil { return err } - j.ArrayMapPtr = new([]map[string]any) - err = connector_Decoder.DecodeNullableObjectValue(j.ArrayMapPtr, input, "ArrayMapPtr") + j.ArrayMapPtr, err = utils.DecodeNullableObjectValue[[]map[string]any](input, "ArrayMapPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.ArrayObject, input, "ArrayObject") + j.ArrayObject, err = utils.DecodeObjectValue[[]struct { + Content string `json:"content"` + }](input, "ArrayObject") if err != nil { return err } - j.ArrayObjectPtr = new([]struct { - Content string "json:\"content\"" - }) - err = connector_Decoder.DecodeNullableObjectValue(j.ArrayObjectPtr, input, "ArrayObjectPtr") + j.ArrayObjectPtr, err = utils.DecodeNullableObjectValue[[]struct { + Content string `json:"content"` + }](input, "ArrayObjectPtr") if err != nil { return err } @@ -201,12 +199,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.BigInt, input, "BigInt") + j.BigInt, err = utils.DecodeObjectValue[scalar.BigInt](input, "BigInt") if err != nil { return err } - j.BigIntPtr = new(scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.BigIntPtr, input, "BigIntPtr") + j.BigIntPtr, err = utils.DecodeNullableObjectValue[scalar.BigInt](input, "BigIntPtr") if err != nil { return err } @@ -218,43 +215,39 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Bytes, input, "Bytes") + j.Bytes, err = utils.DecodeObjectValue[scalar.Bytes](input, "Bytes") if err != nil { return err } - j.BytesPtr = new(scalar.Bytes) - err = connector_Decoder.DecodeNullableObjectValue(j.BytesPtr, input, "BytesPtr") + j.BytesPtr, err = utils.DecodeNullableObjectValue[scalar.Bytes](input, "BytesPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.CustomScalar, input, "CustomScalar") + j.CustomScalar, err = utils.DecodeObjectValue[types.CommentText](input, "CustomScalar") if err != nil { return err } - j.CustomScalarPtr = new(types.CommentText) - err = connector_Decoder.DecodeNullableObjectValue(j.CustomScalarPtr, input, "CustomScalarPtr") + j.CustomScalarPtr, err = utils.DecodeNullableObjectValue[types.CommentText](input, "CustomScalarPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Date, input, "Date") + j.Date, err = utils.DecodeObjectValue[scalar.Date](input, "Date") if err != nil { return err } - j.DatePtr = new(scalar.Date) - err = connector_Decoder.DecodeNullableObjectValue(j.DatePtr, input, "DatePtr") + j.DatePtr, err = utils.DecodeNullableObjectValue[scalar.Date](input, "DatePtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Duration, input, "Duration") + j.Duration, err = utils.DecodeObjectValue[scalar.Duration](input, "Duration") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Enum, input, "Enum") + j.Enum, err = utils.DecodeObjectValue[types.SomeEnum](input, "Enum") if err != nil { return err } - j.EnumPtr = new(types.SomeEnum) - err = connector_Decoder.DecodeNullableObjectValue(j.EnumPtr, input, "EnumPtr") + j.EnumPtr, err = utils.DecodeNullableObjectValue[types.SomeEnum](input, "EnumPtr") if err != nil { return err } @@ -322,57 +315,54 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Map, input, "Map") + j.Map, err = utils.DecodeObjectValue[map[string]any](input, "Map") if err != nil { return err } - j.MapPtr = new(map[string]any) - err = connector_Decoder.DecodeNullableObjectValue(j.MapPtr, input, "MapPtr") + j.MapPtr, err = utils.DecodeNullableObjectValue[map[string]any](input, "MapPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.NamedArray, input, "NamedArray") + j.NamedArray, err = utils.DecodeObjectValue[[]types.Author](input, "NamedArray") if err != nil { return err } - j.NamedArrayPtr = new([]types.Author) - err = connector_Decoder.DecodeNullableObjectValue(j.NamedArrayPtr, input, "NamedArrayPtr") + j.NamedArrayPtr, err = utils.DecodeNullableObjectValue[[]types.Author](input, "NamedArrayPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.NamedObject, input, "NamedObject") + j.NamedObject, err = utils.DecodeObjectValue[types.Author](input, "NamedObject") if err != nil { return err } - j.NamedObjectPtr = new(types.Author) - err = connector_Decoder.DecodeNullableObjectValue(j.NamedObjectPtr, input, "NamedObjectPtr") + j.NamedObjectPtr, err = utils.DecodeNullableObjectValue[types.Author](input, "NamedObjectPtr") if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Object, input, "Object") + j.Object, err = utils.DecodeObjectValue[struct { + ID uuid.UUID `json:"id"` + CreatedAt time.Time `json:"created_at"` + GenericField types.CustomHeadersResult[types.Author] `json:"generic_field,omitempty"` + }](input, "Object") if err != nil { return err } - j.ObjectPtr = new(struct { + j.ObjectPtr, err = utils.DecodeNullableObjectValue[struct { Long int Lat int - }) - err = connector_Decoder.DecodeNullableObjectValue(j.ObjectPtr, input, "ObjectPtr") + }](input, "ObjectPtr") if err != nil { return err } - j.PtrArrayBigInt = new([]scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBigInt, input, "PtrArrayBigInt") + j.PtrArrayBigInt, err = utils.DecodeNullableObjectValue[[]scalar.BigInt](input, "PtrArrayBigInt") if err != nil { return err } - j.PtrArrayBigIntPtr = new([]*scalar.BigInt) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBigIntPtr, input, "PtrArrayBigIntPtr") + j.PtrArrayBigIntPtr, err = utils.DecodeNullableObjectValue[[]*scalar.BigInt](input, "PtrArrayBigIntPtr") if err != nil { return err } - j.PtrArrayBool = new([]bool) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayBool, input, "PtrArrayBool") + j.PtrArrayBool, err = utils.DecodeNullableObjectValue[[]bool](input, "PtrArrayBool") if err != nil { return err } @@ -380,8 +370,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayFloat32 = new([]float32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayFloat32, input, "PtrArrayFloat32") + j.PtrArrayFloat32, err = utils.DecodeNullableObjectValue[[]float32](input, "PtrArrayFloat32") if err != nil { return err } @@ -389,8 +378,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayFloat64 = new([]float64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayFloat64, input, "PtrArrayFloat64") + j.PtrArrayFloat64, err = utils.DecodeNullableObjectValue[[]float64](input, "PtrArrayFloat64") if err != nil { return err } @@ -398,13 +386,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayInt = new([]int) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt, input, "PtrArrayInt") + j.PtrArrayInt, err = utils.DecodeNullableObjectValue[[]int](input, "PtrArrayInt") if err != nil { return err } - j.PtrArrayInt16 = new([]int16) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt16, input, "PtrArrayInt16") + j.PtrArrayInt16, err = utils.DecodeNullableObjectValue[[]int16](input, "PtrArrayInt16") if err != nil { return err } @@ -412,8 +398,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayInt32 = new([]int32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt32, input, "PtrArrayInt32") + j.PtrArrayInt32, err = utils.DecodeNullableObjectValue[[]int32](input, "PtrArrayInt32") if err != nil { return err } @@ -421,8 +406,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayInt64 = new([]int64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt64, input, "PtrArrayInt64") + j.PtrArrayInt64, err = utils.DecodeNullableObjectValue[[]int64](input, "PtrArrayInt64") if err != nil { return err } @@ -430,8 +414,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayInt8 = new([]int8) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayInt8, input, "PtrArrayInt8") + j.PtrArrayInt8, err = utils.DecodeNullableObjectValue[[]int8](input, "PtrArrayInt8") if err != nil { return err } @@ -443,8 +426,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayJSON = new([]any) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayJSON, input, "PtrArrayJSON") + j.PtrArrayJSON, err = utils.DecodeNullableObjectValue[[]any](input, "PtrArrayJSON") if err != nil { return err } @@ -452,8 +434,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayRawJSON = new([]json.RawMessage) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayRawJSON, input, "PtrArrayRawJSON") + j.PtrArrayRawJSON, err = utils.DecodeNullableObjectValue[[]json.RawMessage](input, "PtrArrayRawJSON") if err != nil { return err } @@ -461,8 +442,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayString = new([]string) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayString, input, "PtrArrayString") + j.PtrArrayString, err = utils.DecodeNullableObjectValue[[]string](input, "PtrArrayString") if err != nil { return err } @@ -470,8 +450,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayTime = new([]time.Time) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayTime, input, "PtrArrayTime") + j.PtrArrayTime, err = utils.DecodeNullableObjectValue[[]time.Time](input, "PtrArrayTime") if err != nil { return err } @@ -479,8 +458,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUUID = new([]uuid.UUID) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUUID, input, "PtrArrayUUID") + j.PtrArrayUUID, err = utils.DecodeNullableObjectValue[[]uuid.UUID](input, "PtrArrayUUID") if err != nil { return err } @@ -488,13 +466,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUint = new([]uint) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint, input, "PtrArrayUint") + j.PtrArrayUint, err = utils.DecodeNullableObjectValue[[]uint](input, "PtrArrayUint") if err != nil { return err } - j.PtrArrayUint16 = new([]uint16) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint16, input, "PtrArrayUint16") + j.PtrArrayUint16, err = utils.DecodeNullableObjectValue[[]uint16](input, "PtrArrayUint16") if err != nil { return err } @@ -502,8 +478,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUint32 = new([]uint32) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint32, input, "PtrArrayUint32") + j.PtrArrayUint32, err = utils.DecodeNullableObjectValue[[]uint32](input, "PtrArrayUint32") if err != nil { return err } @@ -511,8 +486,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUint64 = new([]uint64) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint64, input, "PtrArrayUint64") + j.PtrArrayUint64, err = utils.DecodeNullableObjectValue[[]uint64](input, "PtrArrayUint64") if err != nil { return err } @@ -520,8 +494,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - j.PtrArrayUint8 = new([]uint8) - err = connector_Decoder.DecodeNullableObjectValue(j.PtrArrayUint8, input, "PtrArrayUint8") + j.PtrArrayUint8, err = utils.DecodeNullableObjectValue[[]uint8](input, "PtrArrayUint8") if err != nil { return err } @@ -549,12 +522,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.Text, input, "Text") + j.Text, err = utils.DecodeObjectValue[types.Text](input, "Text") if err != nil { return err } - j.TextPtr = new(types.Text) - err = connector_Decoder.DecodeNullableObjectValue(j.TextPtr, input, "TextPtr") + j.TextPtr, err = utils.DecodeNullableObjectValue[types.Text](input, "TextPtr") if err != nil { return err } @@ -566,7 +538,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeObjectValue(&j.URL, input, "URL") + j.URL, err = utils.DecodeObjectValue[scalar.URL](input, "URL") if err != nil { return err } @@ -622,11 +594,11 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.ArrayBigIntEmpty, input, "array_bigint_empty") + j.ArrayBigIntEmpty, err = utils.DecodeObjectValueDefault[[]scalar.BigInt](input, "array_bigint_empty") if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.ArrayBigIntPtrEmpty, input, "array_bigint_ptr_empty") + j.ArrayBigIntPtrEmpty, err = utils.DecodeObjectValueDefault[[]*scalar.BigInt](input, "array_bigint_ptr_empty") if err != nil { return err } @@ -702,7 +674,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.ArrayMapEmpty, input, "array_map_empty") + j.ArrayMapEmpty, err = utils.DecodeObjectValueDefault[[]map[string]any](input, "array_map_empty") if err != nil { return err } @@ -778,7 +750,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.BigIntEmpty, input, "bigint_empty") + j.BigIntEmpty, err = utils.DecodeObjectValueDefault[scalar.BigInt](input, "bigint_empty") if err != nil { return err } @@ -786,15 +758,15 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.CustomScalarEmpty, input, "custom_scalar_empty") + j.CustomScalarEmpty, err = utils.DecodeObjectValueDefault[types.CommentText](input, "custom_scalar_empty") if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.DateEmpty, input, "date_empty") + j.DateEmpty, err = utils.DecodeObjectValueDefault[scalar.Date](input, "date_empty") if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.EnumEmpty, input, "enum_empty") + j.EnumEmpty, err = utils.DecodeObjectValueDefault[types.SomeEnum](input, "enum_empty") if err != nil { return err } @@ -826,7 +798,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.MapEmpty, input, "map_empty") + j.MapEmpty, err = utils.DecodeObjectValueDefault[map[string]any](input, "map_empty") if err != nil { return err } @@ -838,7 +810,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.TextEmpty, input, "text_empty") + j.TextEmpty, err = utils.DecodeObjectValueDefault[types.Text](input, "text_empty") if err != nil { return err } @@ -866,7 +838,7 @@ func (j *GetTypesArguments) FromValue(input map[string]any) error { if err != nil { return err } - err = connector_Decoder.DecodeNullableObjectValue(&j.URLEmpty, input, "url_empty") + j.URLEmpty, err = utils.DecodeObjectValueDefault[scalar.URL](input, "url_empty") if err != nil { return err } @@ -994,6 +966,7 @@ func (j GetTypesArguments) ToMap() map[string]any { } j_Object_obj := make(map[string]any) j_Object_obj["created_at"] = j.Object.CreatedAt + j_Object_obj["generic_field"] = j.Object.GenericField j_Object_obj["id"] = j.Object.ID r["Object"] = j_Object_obj if j.ObjectPtr != nil { diff --git a/example/codegen/types/types.generated.go b/example/codegen/types/types.generated.go index e27e7d4..b9ce9e0 100644 --- a/example/codegen/types/types.generated.go +++ b/example/codegen/types/types.generated.go @@ -8,13 +8,10 @@ import ( "slices" ) -var connector_Decoder = utils.NewDecoder() - // FromValue decodes values from map func (j *Author) FromValue(input map[string]any) error { var err error - j.Author = new(Author) - err = connector_Decoder.DecodeNullableObjectValue(j.Author, input, "author") + j.Author, err = utils.DecodeNullableObjectValue[Author](input, "author") if err != nil { return err } @@ -26,8 +23,7 @@ func (j *Author) FromValue(input map[string]any) error { if err != nil { return err } - j.Status = new(AuthorStatus) - err = connector_Decoder.DecodeNullableObjectValue(j.Status, input, "status") + j.Status, err = utils.DecodeNullableObjectValue[AuthorStatus](input, "status") if err != nil { return err } diff --git a/utils/decode.go b/utils/decode.go index cbdff3a..5230de9 100644 --- a/utils/decode.go +++ b/utils/decode.go @@ -26,10 +26,9 @@ type ( ) var ( - errIntRequired = errors.New("the Int value must not be null") - errUintRequired = errors.New("the Uint value must not be null") - errValueTargetRequired = errors.New("the decoded target must be a pointer and not null") - errValueRequired = errors.New("the value must not be null") + errIntRequired = errors.New("the Int value must not be null") + errUintRequired = errors.New("the Uint value must not be null") + errValueRequired = errors.New("the value must not be null") ) // ValueDecoder abstracts a type with the FromValue method to decode any value. @@ -57,6 +56,8 @@ type Decoder struct { } // NewDecoder creates a Decoder instance. +// +// Deprecated: use the generic DecodeValue and DecodeObjectValue functions instead func NewDecoder(decodeHooks ...mapstructure.DecodeHookFunc) *Decoder { return &Decoder{ decodeHook: mapstructure.ComposeDecodeHookFunc(append(defaultDecodeFuncs, decodeHooks...)...), @@ -64,6 +65,8 @@ func NewDecoder(decodeHooks ...mapstructure.DecodeHookFunc) *Decoder { } // DecodeObjectValue get and decode a value from object by key. +// +// Deprecated: use the generic DecodeObjectValue function instead func (d Decoder) DecodeObjectValue(target any, object map[string]any, key string) error { value, ok := GetAny(object, key) if !ok { @@ -77,6 +80,8 @@ func (d Decoder) DecodeObjectValue(target any, object map[string]any, key string } // DecodeNullableObjectValue get and decode a nullable value from object by key. +// +// Deprecated: use the generic DecodeNullableObjectValue function instead func (d Decoder) DecodeNullableObjectValue(target any, object map[string]any, key string) error { value, ok := GetAny(object, key) if !ok { @@ -91,24 +96,140 @@ func (d Decoder) DecodeNullableObjectValue(target any, object map[string]any, ke // DecodeValue tries to convert and set an unknown value into the target, the value must not be null // fallback to mapstructure decoder. +// +// Deprecated: use the generic DecodeValue function instead func (d Decoder) DecodeValue(target any, value any) error { - return d.decodeValue(target, value) + return decodeValue(target, value, d.decodeHook) } // DecodeNullableValue tries to convert and set an unknown value into the target, // fallback to mapstructure decoder. +// +// Deprecated: use the generic DecodeNullableValue function instead func (d Decoder) DecodeNullableValue(target any, value any) error { - err := d.decodeValue(target, value) + err := decodeValue(target, value, d.decodeHook) if err != nil && !errors.Is(err, errValueRequired) { return err } return nil } -func (d Decoder) decodeValue(target any, value any) error { +// DecodeObject tries to decode an object from a map. +// +// Deprecated: use the generic DecodeObject function instead +func (d Decoder) DecodeObject(target any, value map[string]any) error { + if len(value) == 0 { + return nil + } if IsNil(target) { - return errValueTargetRequired + return errors.New("the decoded target must be not null") + } + + if t, ok := target.(ObjectDecoder); ok { + return t.FromValue(value) + } + + return decodeAnyValue(target, value, d.decodeHook) +} + +// DecodeObjectValue get and decode a value from object by key. +func DecodeObjectValue[T any](object map[string]any, key string, decodeHooks ...mapstructure.DecodeHookFunc) (T, error) { + value, ok := GetAny(object, key) + if !ok { + var result T + return result, fmt.Errorf("%s: field is required", key) + } + result, err := DecodeValue[T](value, decodeHooks...) + if err != nil { + return result, fmt.Errorf("%s: %w", key, err) } + return result, nil +} + +// DecodeObjectValueDefault get and decode a value from object by key. Returns the empty object if the input value is null. +func DecodeObjectValueDefault[T any](object map[string]any, key string, decodeHooks ...mapstructure.DecodeHookFunc) (T, error) { + result, err := DecodeNullableObjectValue[T](object, key, decodeHooks...) + if err != nil || result == nil { + var emptyValue T + return emptyValue, err + } + return *result, nil +} + +// DecodeNullableObjectValue get and decode a nullable value from object by key. +func DecodeNullableObjectValue[T any](object map[string]any, key string, decodeHooks ...mapstructure.DecodeHookFunc) (*T, error) { + value, ok := GetAny(object, key) + if !ok { + return nil, nil + } + result, err := DecodeNullableValue[T](value, decodeHooks...) + if err != nil { + return nil, fmt.Errorf("%s: %w", key, err) + } + return result, nil +} + +// DecodeValue tries to convert and set an unknown value into the target, the value must not be null +// fallback to mapstructure decoder. +func DecodeValue[T any](value any, decodeHooks ...mapstructure.DecodeHookFunc) (T, error) { + result := new(T) + err := decodeValue(result, value, decodeHooks...) + return *result, err +} + +// DecodeNullableValue tries to convert and set an unknown value into the target, +// fallback to mapstructure decoder. +func DecodeNullableValue[T any](value any, decodeHooks ...mapstructure.DecodeHookFunc) (*T, error) { + result := new(T) + err := decodeValue(result, value, decodeHooks...) + if err != nil { + if errors.Is(err, errValueRequired) { + return nil, nil + } + return nil, err + } + return result, nil +} + +// DecodeObject tries to decode an object from a map. +func DecodeObject[T any](value map[string]any, decodeHooks ...mapstructure.DecodeHookFunc) (T, error) { + result := new(T) + if len(value) == 0 { + return *result, nil + } + + if t, ok := any(result).(ObjectDecoder); ok { + if err := t.FromValue(value); err != nil { + return *result, err + } + } + + err := decodeAnyValue(result, value, decodeHooks...) + return *result, err +} + +// DecodeNullableObject tries to decode an object from a map. +func DecodeNullableObject[T any](value map[string]any, decodeHooks ...mapstructure.DecodeHookFunc) (*T, error) { + if value == nil { + return nil, nil + } + + result := new(T) + if len(value) == 0 { + return result, nil + } + + if t, ok := any(result).(ObjectDecoder); ok { + if err := t.FromValue(value); err != nil { + return nil, err + } + } + + err := decodeAnyValue(result, value, decodeHooks...) + return result, err +} + +func decodeValue(target any, value any, decodeHooks ...mapstructure.DecodeHookFunc) error { if IsNil(value) { return errValueRequired } @@ -125,8 +246,6 @@ func (d Decoder) decodeValue(target any, value any) error { } case ValueDecoder: return t.FromValue(value) - case bool, string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128, time.Time, time.Duration, time.Ticker: - return errors.New("the decoded target must be a pointer") case *complex64, *complex128: return errors.New("unsupported complex types") case *bool: @@ -436,28 +555,12 @@ func (d Decoder) decodeValue(target any, value any) error { } *t = *v default: - return decodeAnyValue(target, value, d.decodeHook) + return decodeAnyValue(target, value, decodeHooks...) } return nil } -// DecodeObject tries to decode an object from a map. -func (d Decoder) DecodeObject(target any, value map[string]any) error { - if len(value) == 0 { - return nil - } - if IsNil(target) { - return errors.New("the decoded target must be not null") - } - - if t, ok := target.(ObjectDecoder); ok { - return t.FromValue(value) - } - - return decodeAnyValue(target, value, d.decodeHook) -} - // DecodeNullableInt tries to convert an unknown value to a nullable integer. func DecodeNullableInt[T int | int8 | int16 | int32 | int64](value any) (*T, error) { return decodeNullableInt(value, convertInt[T]) @@ -1454,11 +1557,11 @@ func GetRawJSONDefault(object map[string]any, key string) (json.RawMessage, erro return *result, nil } -func decodeAnyValue(target any, value any, decodeHook mapstructure.DecodeHookFunc) error { +func decodeAnyValue(target any, value any, decodeHooks ...mapstructure.DecodeHookFunc) error { decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ Result: target, TagName: "json", - DecodeHook: decodeHook, + DecodeHook: mapstructure.ComposeDecodeHookFunc(append(defaultDecodeFuncs, decodeHooks...)...), }) if err != nil { return err diff --git a/utils/decode_test.go b/utils/decode_test.go index f87eb52..99cf040 100644 --- a/utils/decode_test.go +++ b/utils/decode_test.go @@ -963,3 +963,23 @@ func TestDecodeNestedInterface(t *testing.T) { _, err = GetNullableFloatSlice[float32](fixture, "floatSlicePtr") assert.NilError(t, err) } + +func TestDecodeNullableObjectValue(t *testing.T) { + type testObject struct { + Name string `json:"name"` + } + + t.Run("null", func(t *testing.T) { + result, err := DecodeNullableValue[testObject](nil) + assert.NilError(t, err) + assert.Assert(t, result == nil) + }) + + t.Run("not_null", func(t *testing.T) { + result, err := DecodeNullableValue[testObject](map[string]any{ + "name": "foo", + }) + assert.NilError(t, err) + assert.Equal(t, result.Name, "foo") + }) +}