Lookup a user default for this function
(ctx context.Context, argName string)
| 551 | |
| 552 | // Lookup a user default for this function |
| 553 | func (fn *ModuleFunction) UserDefault(ctx context.Context, argName string) (*UserDefault, bool, error) { |
| 554 | // Lookup the argument typedef |
| 555 | arg, ok := fn.metadata.LookupArg(argName) |
| 556 | if !ok { |
| 557 | return nil, false, fmt.Errorf("lookup default: function %q has no argument %q", fn.metadata.Name, argName) |
| 558 | } |
| 559 | |
| 560 | isConstructor := fn.metadata.Name == "" |
| 561 | |
| 562 | // TODO(workspace-env-expansion): Implement ${VAR} expansion for workspace config string values. |
| 563 | // |
| 564 | // Spec: |
| 565 | // - $VAR and ${VAR} in string config values should resolve to system environment variables |
| 566 | // - NO cascading: $FOO always means the system env var FOO, never another config key |
| 567 | // - Resolution should go through the Workspace type (gateway for client context access) |
| 568 | // - The Workspace type should expose a method for resolving system env vars, |
| 569 | // which can later be gated by interactive prompts, allow/deny policies, value injection |
| 570 | // - Consider docker-compose's variable substitution spec as reference for syntax |
| 571 | // - For now, string values pass through as-is (no expansion) |
| 572 | |
| 573 | // PATH A: Workspace config (constructor only, no EnvFile) |
| 574 | if fn.mod.Self().WorkspaceConfig != nil && isConstructor { |
| 575 | val, ok := lookupConfigCaseInsensitive(fn.mod.Self().WorkspaceConfig, arg.Self().OriginalName, arg.Self().Name) |
| 576 | if ok { |
| 577 | return fn.newUserDefault(arg.Self(), configValueToString(val)), true, nil |
| 578 | } |
| 579 | // Not in workspace config — only fall through to .env if enabled |
| 580 | if !fn.mod.Self().DefaultsFromDotEnv { |
| 581 | return nil, false, nil |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | // PATH B: existing .env pipeline (completely unchanged) |
| 586 | // We need access to the main client's context for resolving system env variables |
| 587 | // (otherwise we may resolve them in the module container's context) |
| 588 | // so we upgrade the context to the main client. |
| 589 | query, err := CurrentQuery(ctx) |
| 590 | if err != nil { |
| 591 | return nil, false, fmt.Errorf("get current query: %w", err) |
| 592 | } |
| 593 | mainClient, err := query.NonModuleParentClientMetadata(ctx) |
| 594 | if err != nil { |
| 595 | return nil, false, fmt.Errorf("access main client: %w", err) |
| 596 | } |
| 597 | mainCtx := engine.ContextWithClientMetadata(ctx, mainClient) |
| 598 | // Get all defaults for this function |
| 599 | // FIXME: we shouldn't need the main client context here (we don't need to evaluate env values yet) |
| 600 | defaults, err := fn.UserDefaults(mainCtx) |
| 601 | if err != nil { |
| 602 | return nil, false, fmt.Errorf("lookup defaults for function %q: %w", fn.metadata.Name, err) |
| 603 | } |
| 604 | userInput, ok, err := defaults.LookupCaseInsensitive(mainCtx, arg.Self().Name) |
| 605 | if err != nil { |
| 606 | return nil, false, err |
| 607 | } |
| 608 | if !ok { |
| 609 | return nil, false, nil |
| 610 | } |
no test coverage detected