Documentation
¶
Overview ¶
Package migrate generates a .defederator.yml plus a stub cross_service/client.go from an existing genqlient.yaml, so a service can switch from genqlient to defederator with minimal manual edits.
Index ¶
- func DefederatorYAML(in *YAMLInput) (string, error)
- func LintFixHint() string
- func LoadOperationSources(patterns []string, baseDir string) ([]*ast.Source, error)
- func OperationUsedEnums(schema *ast.Schema, sources []*ast.Source) ([]string, error)
- func OperationVariableInputObjects(schema *ast.Schema, sources []*ast.Source) ([]string, error)
- func Render(d *Data) (string, error)
- func Run(_ context.Context, dir string, opts Options) error
- func UsedSubgraphs(sg *federation.Supergraph, sources []*ast.Source) []string
- type AuthFlavors
- type Data
- type GenqlientConfig
- type Options
- type SubgraphEntry
- type YAMLInput
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefederatorYAML ¶
DefederatorYAML converts a migration input into a .defederator.yml YAML string. Pure function — no I/O.
Conversion rules:
- schema: → schema: (verbatim)
- operations: → query: (same list)
- generated: → client.filename: (path with genqlient replaced by defederator, ./ prefix)
- bindings: → kept verbatim from genqlient.yaml (defederator generate runs inside the webapp module, so package paths like github.com/Khan/webapp/pkg/content.Author resolve correctly)
- url_mode: enum is always added (webapp supergraph uses placeholder URLs)
- generate.clientInterfaceName: FederationClient is always added
- generate.optional: pointer is always added
- INPUT_OBJECT types from the supergraph SDL are added as genqlient-package bindings
func LintFixHint ¶
func LintFixHint() string
LintFixHint returns the single-line suggestion printed after a successful migrate run. After recompilation, the webapp kacontextinterface analyzer (ADR-429) commonly flags ctx interfaces that now transitively reference service_discovery.KAContext. The analyzer emits SuggestedFix records that golangci-lint applies in place when invoked with --fix, so the user can resolve the whole batch with one command rather than hand-editing each site.
func LoadOperationSources ¶
LoadOperationSources reads every operation file listed in genqlient.yaml's `operations:` (or `query:`) section and returns one gqlparser ast.Source per operation string. Glob patterns are expanded relative to baseDir.
Both .graphql and .go files are supported: .go files are scanned for `# @genqlient`-tagged string literals (via generator.QuerySourcesFromGoFile).
Used by migrate to identify which subgraphs and INPUT_OBJECT types the service's operations actually reference, so the generated `.defederator.yml` and `cross_service/client.go` can be pruned accordingly.
func OperationUsedEnums ¶
OperationUsedEnums returns the sorted, deduplicated set of enum type names that appear in any operation's variable types or response selection field types across the given sources, restricted to types declared in schema.
Used to emit enum bindings in `.defederator.yml` that point at the corresponding genqlient-generated Go types. This way the user's existing genqlient-typed values (e.g. genqlient.OptOutStatusOptedIn) can be passed to defederator client methods without casts.
func OperationVariableInputObjects ¶
OperationVariableInputObjects returns the sorted, deduplicated set of INPUT_OBJECT type names that appear as operation variable types across the given query sources, restricted to types declared in schema.
Used to prune the `.defederator.yml` bindings: only INPUT_OBJECTs actually passed as cross-service operation arguments need a binding.
func Run ¶
Run migrates a genqlient-based service directory to defederator.
Files are not overwritten unless opts.Force is true. With opts.DryRun, files are printed to stdout and not written.
func UsedSubgraphs ¶
func UsedSubgraphs(sg *federation.Supergraph, sources []*ast.Source) []string
UsedSubgraphs returns the sorted, deduplicated set of join__Graph enum names that the given operation sources actually touch, as determined by planning each operation with the federation query planner.
Used to prune `_subgraphServices` in the generated cross_service/client.go: only subgraphs whose fields appear in at least one operation need a service-discovery lookup at runtime.
An operation that fails to plan (e.g. references a type the supergraph doesn't have, which would be a programmer error) is skipped silently so that migrate is no stricter than `defederator generate` itself.
Types ¶
type AuthFlavors ¶
AuthFlavors records which gqlclient auth modes a service's cross-service code invokes. Each field is true when at least one call site in the operation Go files uses the corresponding pattern:
- User: ctx.GraphQL().AsUser()
- Admin: ctx.GraphQL().AsServiceAdmin()
- LocaleUser: ctx.GraphQL().WithKALocale(...).AsUser()
The set drives which federation-client constructors migrate emits in cross_service/client.go.
func AuthFlavorsFromOperationDir ¶
func AuthFlavorsFromOperationDir(dir string) (AuthFlavors, error)
AuthFlavorsFromOperationDir scans every .go file in the given directory (non-recursive) and returns the union of auth flavors detected. This is the convenience entrypoint migrate.Run uses: the migrate command knows the cross_service dir, hands it here, and gets back the flavor set.
func DetectAuthFlavors ¶
func DetectAuthFlavors(goFiles []string) (AuthFlavors, error)
DetectAuthFlavors scans the contents of the given Go source files for gqlclient auth-mode call chains and returns the union of flavors found.
Missing files are skipped silently. Read errors return immediately with the error; caller decides whether to proceed with a partial result.
Detection is regex-based on raw source text rather than AST: every flavor we care about has a unique, unambiguous lexical form (an `.AsXxx()` method call at the end of a chain). False positives in comments are unlikely in practice because webapp cross-service files don't quote these call chains.
func (AuthFlavors) Any ¶
func (a AuthFlavors) Any() bool
Any reports whether any flavor was detected. Used by the template to decide between the single-constructor default and the multi-factory shape.
func (AuthFlavors) Multi ¶
func (a AuthFlavors) Multi() bool
Multi reports whether more than one flavor is present, which is the signal that the multi-factory pattern is required (separate User/Admin/LocaleUser constructors plus a shared newJobFederationClient).
type Data ¶
type Data struct {
ServiceName string // e.g. "ai-guide"
ServiceDir string // absolute or relative path passed to migrate
PackageName string // always "cross_service"
ImportAlias string // always "defed"
DefedImportPath string // e.g. "github.com/Khan/webapp/services/ai-guide/generated/defederator"
URLFuncName string // e.g. "aiGuideSubgraphURLs"
Subgraphs []SubgraphEntry // join__Graph entries the service touches
AuthFlavors AuthFlavors // which factory shape to emit
}
Data holds all values the client.gotpl template needs.
func DataFromDir ¶
func DataFromDir( dir string, modulePath string, subgraphs []SubgraphEntry, flavors AuthFlavors, ) *Data
DataFromDir derives template Data from the service directory path, the webapp module path (from go.mod), the (already-pruned) subgraph list, and the detected auth flavors. Pure function — no I/O.
type GenqlientConfig ¶
type GenqlientConfig struct {
Schema string
Operations []string
Generated string
Bindings map[string]config.TypeBinding
}
GenqlientConfig is the parsed subset of a genqlient.yaml relevant to migration.
type Options ¶
type Options struct {
Force bool // overwrite existing .defederator.yml and client.go
DryRun bool // print what would be written; write nothing
// SkipNextSteps suppresses the post-migration instruction block. Set when
// the caller is going to chain into another step (e.g. generate) that
// makes the printed advice misleading.
SkipNextSteps bool
}
Options configures a migration run.
type SubgraphEntry ¶
type SubgraphEntry struct {
EnumName string // e.g. "AI_GUIDE"
ServiceName string // e.g. "ai-guide" (from @join__graph identifier directive arg)
}
SubgraphEntry is a single join__Graph enum value parsed from the supergraph SDL.
func FilterSubgraphs ¶
func FilterSubgraphs( all []SubgraphEntry, usedEnumNames []string, ownServiceName string, ) []SubgraphEntry
FilterSubgraphs keeps only the SubgraphEntries whose EnumName appears in usedEnumNames, preserving original declaration order. The own-service entry (matching ownServiceName) is always kept regardless of usage so that the generated map looks complete for the local service.
usedEnumNames must be sorted; passing the result of UsedSubgraphs satisfies that. ownServiceName may be "" to skip the always-keep behavior.
func ParseSubgraphs ¶
func ParseSubgraphs(sdl string) ([]SubgraphEntry, error)
ParseSubgraphs reads a Federation v2 supergraph SDL and returns all join__Graph enum values in declaration order. Pure function — no I/O.
For each enum value, the service name is taken from the @join__graph(identifier:) directive argument. If the argument is absent the service name is derived by lowercasing the enum name and replacing underscores with hyphens.
type YAMLInput ¶
type YAMLInput struct {
Genqlient GenqlientConfig
InputObjects []string // INPUT_OBJECT names used by operations, sorted
Enums []string // ENUM names used by operations, sorted
GenqlientPkg string // e.g. "github.com/Khan/webapp/services/foo/generated/genqlient"
}
YAMLInput collects everything DefederatorYAML needs to produce a .defederator.yml. It is the pure-function boundary: the caller resolves I/O; DefederatorYAML is a pure transformation.