| 2480 | } |
| 2481 | |
| 2482 | func setInputObjectFields(obj any, vals map[string]any) ([]inputObjectField, error) { |
| 2483 | objT := reflect.TypeOf(obj).Elem() |
| 2484 | objV := reflect.ValueOf(obj) |
| 2485 | if objT.Kind() != reflect.Struct { |
| 2486 | // TODO handle pointer? |
| 2487 | return nil, fmt.Errorf("object must be a struct, got %T", obj) |
| 2488 | } |
| 2489 | fields := make([]inputObjectField, 0, objT.NumField()) |
| 2490 | for i := range objT.NumField() { |
| 2491 | fieldT := objT.Field(i) |
| 2492 | fieldV := objV.Elem().Field(i) |
| 2493 | name := fieldT.Tag.Get("name") |
| 2494 | if name == "" { |
| 2495 | name = strcase.ToLowerCamel(fieldT.Name) |
| 2496 | } |
| 2497 | if name == "-" { |
| 2498 | continue |
| 2499 | } |
| 2500 | fieldI := fieldV.Interface() |
| 2501 | if fieldT.Anonymous { |
| 2502 | // embedded struct |
| 2503 | val := reflect.New(fieldT.Type) |
| 2504 | embeddedFields, err := setInputObjectFields(val.Interface(), vals) |
| 2505 | if err != nil { |
| 2506 | return nil, err |
| 2507 | } |
| 2508 | fieldV.Set(val.Elem()) |
| 2509 | fields = append(fields, embeddedFields...) |
| 2510 | continue |
| 2511 | } |
| 2512 | zeroInput, err := builtinOrInput(fieldI) |
| 2513 | if err != nil { |
| 2514 | return nil, fmt.Errorf("arg %q: %w", fieldT.Name, err) |
| 2515 | } |
| 2516 | var input Input |
| 2517 | if val, ok := vals[name]; ok { |
| 2518 | var err error |
| 2519 | input, err = zeroInput.Decoder().DecodeInput(val) |
| 2520 | if err != nil { |
| 2521 | return nil, err |
| 2522 | } |
| 2523 | } else if inputDefStr, hasDefault := fieldT.Tag.Lookup("default"); hasDefault { |
| 2524 | var err error |
| 2525 | input, err = zeroInput.Decoder().DecodeInput(inputDefStr) |
| 2526 | if err != nil { |
| 2527 | return nil, fmt.Errorf("convert default value for arg %s: %w", name, err) |
| 2528 | } |
| 2529 | } else if zeroInput.Type().NonNull { |
| 2530 | return nil, fmt.Errorf("missing required input field %q", name) |
| 2531 | } |
| 2532 | if input != nil { // will be nil for optional fields |
| 2533 | if err := assign(fieldV, input); err != nil { |
| 2534 | return nil, fmt.Errorf("assign input object %q as %+v (%T): %w", fieldT.Name, input, input, err) |
| 2535 | } |
| 2536 | fields = append(fields, inputObjectField{name: name, value: input}) |
| 2537 | } |
| 2538 | } |
| 2539 | return fields, nil |