objFun creates a dagql.Field for a function defined on a module object type. This is used during the GraphQL schema installation process to convert user-defined functions in module object types into callable GraphQL fields. Flow: 1. Called from ModuleObject.functions() during ModuleObject.Install()
(ctx context.Context, mod dagql.ObjectResult[*Module], objDef *ObjectTypeDef, fun *Function, dag *dagql.Server)
| 1397 | // The resulting field enables users to call their custom functions as GraphQL |
| 1398 | // fields on their object types, with proper argument handling and caching. |
| 1399 | func objFun(ctx context.Context, mod dagql.ObjectResult[*Module], objDef *ObjectTypeDef, fun *Function, dag *dagql.Server) (dagql.Field[*ModuleObject], error) { |
| 1400 | var f dagql.Field[*ModuleObject] |
| 1401 | if mod.Self() == nil { |
| 1402 | return f, fmt.Errorf("install function %q without module result wrapper", fun.Name) |
| 1403 | } |
| 1404 | modFun, err := NewModFunction( |
| 1405 | ctx, |
| 1406 | mod, |
| 1407 | objDef, |
| 1408 | fun, |
| 1409 | ) |
| 1410 | if err != nil { |
| 1411 | return f, fmt.Errorf("failed to create function %q: %w", fun.Name, err) |
| 1412 | } |
| 1413 | // Apply local user defaults to the function's arguments, so that they show |
| 1414 | // up in installed typedefs (for introspection) |
| 1415 | if err := modFun.mergeUserDefaultsTypeDefs(ctx); err != nil { |
| 1416 | return f, fmt.Errorf("failed to merge user defaults for %q: %w", fun.Name, err) |
| 1417 | } |
| 1418 | spec, err := modFun.metadata.FieldSpec(ctx, NewUserMod(mod)) |
| 1419 | if err != nil { |
| 1420 | return f, fmt.Errorf("failed to get field spec: %w", err) |
| 1421 | } |
| 1422 | moduleID, err := NewUserMod(mod).ResultCallModule(ctx) |
| 1423 | if err != nil { |
| 1424 | return f, fmt.Errorf("failed to resolve module identity for function %q: %w", fun.Name, err) |
| 1425 | } |
| 1426 | spec.Module = moduleID |
| 1427 | spec.GetDynamicInput = modFun.DynamicInputsForCall |
| 1428 | spec.ImplicitInputs = append(spec.ImplicitInputs, modFun.cacheImplicitInputs()...) |
| 1429 | |
| 1430 | return dagql.Field[*ModuleObject]{ |
| 1431 | Spec: &spec, |
| 1432 | Func: func(ctx context.Context, obj dagql.ObjectResult[*ModuleObject], args map[string]dagql.Input, view call.View) (dagql.AnyResult, error) { |
| 1433 | opts := &CallOpts{ |
| 1434 | ParentTyped: obj, |
| 1435 | ParentFields: obj.Self().Fields, |
| 1436 | SkipSelfSchema: false, |
| 1437 | Server: dag, |
| 1438 | } |
| 1439 | for name, val := range args { |
| 1440 | opts.Inputs = append(opts.Inputs, CallInput{ |
| 1441 | Name: name, |
| 1442 | Value: val, |
| 1443 | }) |
| 1444 | } |
| 1445 | // NB: ensure deterministic order |
| 1446 | sort.Slice(opts.Inputs, func(i, j int) bool { |
| 1447 | return opts.Inputs[i].Name < opts.Inputs[j].Name |
| 1448 | }) |
| 1449 | return modFun.Call(ctx, opts) |
| 1450 | }, |
| 1451 | }, nil |
| 1452 | } |
| 1453 | |
| 1454 | type CallableField struct { |
| 1455 | Module *Module |
no test coverage detected