Clean up godoc (#82)

## Summary:
Before open-sourcing, we want to make sure that (a) GoDoc looks
reasonable, and (b) everything in the API is something we want to commit
to.  In this commit, I do some miscellaneous cleanup on both fronts;
this does involve a few breaking changes to the programmatic API (better
now than once it has users).  In future commits, I'll likely move the
documentation for `genqlient.yaml` and `@genqlient` to clearer places,
and make `GenqlientDirective` private, such that GoDoc is really only
for programmatic users.

Fixes #25.

Issue: https://github.com/Khan/genqlient/issues/25

## Test plan:
make check


Author: benjaminjkraft

Reviewers: dnerdy, benjaminjkraft, jvoll, aberkan, MiguelCastillo, mahtabsabet

Required Reviewers: 

Approved By: dnerdy, jvoll

Checks:  Test (1.17),  Test (1.16),  Test (1.15),  Test (1.14),  Lint,  Test (1.17),  Test (1.16),  Test (1.15),  Test (1.14),  Lint

Pull Request URL: https://github.com/Khan/genqlient/pull/82
This commit is contained in:
Ben Kraft
2021-09-10 15:54:34 -07:00
committed by GitHub
parent dc38360d9d
commit d41cf636af
5 changed files with 54 additions and 36 deletions
+21 -15
View File
@@ -10,6 +10,10 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
// Config represents genqlient's configuration, generally read from
// genqlient.yaml.
//
// Callers must call ValidateAndFillDefaults before using the config.
type Config struct { type Config struct {
// The filename with the GraphQL schema (in SDL format); defaults to // The filename with the GraphQL schema (in SDL format); defaults to
// schema.graphql // schema.graphql
@@ -100,8 +104,9 @@ type Config struct {
// them at your own risk! // them at your own risk!
AllowBrokenFeatures bool `yaml:"allow_broken_features"` AllowBrokenFeatures bool `yaml:"allow_broken_features"`
// Set automatically to the filename of the config file itself. // The directory of the config-file (relative to which all the other paths
configFilename string // are resolved). Set by ValidateAndFillDefaults.
baseDir string
} }
// A TypeBinding represents a Go type to which genqlient will bind a particular // A TypeBinding represents a Go type to which genqlient will bind a particular
@@ -134,22 +139,21 @@ type TypeBinding struct {
ExpectExactFields string `yaml:"expect_exact_fields"` ExpectExactFields string `yaml:"expect_exact_fields"`
} }
// baseDir returns the directory of the config-file (relative to which // ValidateAndFillDefaults ensures that the configuration is valid, and fills
// all the other paths are resolved). // in any options that were unspecified.
func (c *Config) baseDir() string { //
return filepath.Dir(c.configFilename) // The argument is the directory relative to which paths will be interpreted,
} // typically the directory of the config file.
func (c *Config) ValidateAndFillDefaults(baseDir string) error {
func (c *Config) ValidateAndFillDefaults(configFilename string) error { c.baseDir = baseDir
c.configFilename = configFilename
// Make paths relative to config dir // Make paths relative to config dir
c.Schema = filepath.Join(c.baseDir(), c.Schema) c.Schema = filepath.Join(baseDir, c.Schema)
for i := range c.Operations { for i := range c.Operations {
c.Operations[i] = filepath.Join(c.baseDir(), c.Operations[i]) c.Operations[i] = filepath.Join(baseDir, c.Operations[i])
} }
c.Generated = filepath.Join(c.baseDir(), c.Generated) c.Generated = filepath.Join(baseDir, c.Generated)
if c.ExportOperations != "" { if c.ExportOperations != "" {
c.ExportOperations = filepath.Join(c.baseDir(), c.ExportOperations) c.ExportOperations = filepath.Join(baseDir, c.ExportOperations)
} }
if c.ContextType == "" { if c.ContextType == "" {
@@ -173,6 +177,8 @@ func (c *Config) ValidateAndFillDefaults(configFilename string) error {
return nil return nil
} }
// ReadAndValidateConfig reads the configuration from the given file, validates
// it, and returns it.
func ReadAndValidateConfig(filename string) (*Config, error) { func ReadAndValidateConfig(filename string) (*Config, error) {
text, err := ioutil.ReadFile(filename) text, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
@@ -185,7 +191,7 @@ func ReadAndValidateConfig(filename string) (*Config, error) {
return nil, errorf(nil, "invalid config file %v: %v", filename, err) return nil, errorf(nil, "invalid config file %v: %v", filename, err)
} }
err = config.ValidateAndFillDefaults(filename) err = config.ValidateAndFillDefaults(filepath.Dir(filename))
if err != nil { if err != nil {
return nil, errorf(nil, "invalid config file %v: %v", filename, err) return nil, errorf(nil, "invalid config file %v: %v", filename, err)
} }
+6 -5
View File
@@ -329,11 +329,12 @@ func (g *generator) addOperation(op *ast.OperationDefinition) error {
return nil return nil
} }
// Generate returns a map from absolute-path filename to generated content. // Generate is the main programmatic entrypoint to genqlient, and generates and
// returns Go source code based on the given configuration.
// //
// This is the main entrypoint to the code-generation process for callers who // See Config for more on creating a configuration. The return value is a map
// wish to manage the config-reading (ReadAndValidateConfig) and file-writing // from filename to the generated file-content (e.g. Go source). Callers who
// on their own. (Those are wired in by Main.) // don't want to manage reading and writing the files should call Main.
func Generate(config *Config) (map[string][]byte, error) { func Generate(config *Config) (map[string][]byte, error) {
// Step 1: Read in the schema and operations from the files defined by the // Step 1: Read in the schema and operations from the files defined by the
// config (and validate the operations against the schema). This is all // config (and validate the operations against the schema). This is all
@@ -343,7 +344,7 @@ func Generate(config *Config) (map[string][]byte, error) {
return nil, err return nil, err
} }
document, err := getAndValidateQueries(config.baseDir(), config.Operations, schema) document, err := getAndValidateQueries(config.baseDir, config.Operations, schema)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+15 -15
View File
@@ -145,43 +145,43 @@ func defaultConfig(t *testing.T) *Config {
// configurations. It uses snapshots, just like TestGenerate. // configurations. It uses snapshots, just like TestGenerate.
func TestGenerateWithConfig(t *testing.T) { func TestGenerateWithConfig(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
fakeConfigFilename string baseDir string // relative to dataDir
config *Config // omits Schema and Operations, set below. config *Config // omits Schema and Operations, set below.
}{ }{
{"DefaultConfig", "genqlient.yaml", defaultConfig(t)}, {"DefaultConfig", "", defaultConfig(t)},
{"Subpackage", "genqlient.yaml", &Config{ {"Subpackage", "", &Config{
Generated: "mypkg/myfile.go", Generated: "mypkg/myfile.go",
}}, }},
{"SubpackageConfig", "mypkg/genqlient.yaml", &Config{ {"SubpackageConfig", "mypkg", &Config{
Generated: "myfile.go", // (relative to genqlient.yaml) Generated: "myfile.go", // (relative to genqlient.yaml)
}}, }},
{"PackageName", "genqlient.yaml", &Config{ {"PackageName", "", &Config{
Generated: "myfile.go", Generated: "myfile.go",
Package: "mypkg", Package: "mypkg",
}}, }},
{"ExportOperations", "genqlient.yaml", &Config{ {"ExportOperations", "", &Config{
Generated: "generated.go", Generated: "generated.go",
ExportOperations: "operations.json", ExportOperations: "operations.json",
}}, }},
{"CustomContext", "genqlient.yaml", &Config{ {"CustomContext", "", &Config{
Generated: "generated.go", Generated: "generated.go",
ContextType: "github.com/Khan/genqlient/internal/testutil.MyContext", ContextType: "github.com/Khan/genqlient/internal/testutil.MyContext",
}}, }},
{"NoContext", "genqlient.yaml", &Config{ {"NoContext", "", &Config{
Generated: "generated.go", Generated: "generated.go",
ContextType: "-", ContextType: "-",
}}, }},
{"ClientGetter", "genqlient.yaml", &Config{ {"ClientGetter", "", &Config{
Generated: "generated.go", Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromContext", ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromContext",
}}, }},
{"ClientGetterCustomContext", "genqlient.yaml", &Config{ {"ClientGetterCustomContext", "", &Config{
Generated: "generated.go", Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromMyContext", ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromMyContext",
ContextType: "github.com/Khan/genqlient/internal/testutil.MyContext", ContextType: "github.com/Khan/genqlient/internal/testutil.MyContext",
}}, }},
{"ClientGetterNoContext", "genqlient.yaml", &Config{ {"ClientGetterNoContext", "", &Config{
Generated: "generated.go", Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromNowhere", ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromNowhere",
ContextType: "-", ContextType: "-",
@@ -192,9 +192,9 @@ func TestGenerateWithConfig(t *testing.T) {
for _, test := range tests { for _, test := range tests {
config := test.config config := test.config
baseDir := filepath.Join(dataDir, test.baseDir)
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
err := config.ValidateAndFillDefaults( err := config.ValidateAndFillDefaults(baseDir)
filepath.Join(dataDir, test.fakeConfigFilename))
config.Schema = filepath.Join(dataDir, "schema.graphql") config.Schema = filepath.Join(dataDir, "schema.graphql")
config.Operations = []string{filepath.Join(dataDir, sourceFilename)} config.Operations = []string{filepath.Join(dataDir, sourceFilename)}
if err != nil { if err != nil {
+6
View File
@@ -1,3 +1,6 @@
// Package generate provides programmatic access to genqlient's functionality,
// and documentation of its configuration options. For general usage
// documentation, see github.com/Khan/genqlient.
package generate package generate
import ( import (
@@ -50,6 +53,9 @@ See https://github.com/Khan/genqlient for full documentation.
`) `)
} }
// Main is the command-line entrypoint to genqlient; it's equivalent to calling
// `go run github.com/Khan/genqlient`. For lower-level control over
// genqlient's operation, see Generate.
func Main() { func Main() {
exitIfError := func(err error) { exitIfError := func(err error) {
if err != nil { if err != nil {
+6 -1
View File
@@ -1,4 +1,9 @@
// package main is at the root to allow "go run github.com/Khan/genqlient" // genqlient is a GraphQL client generator for Go.
//
// To run genqlient:
// go run github.com/Khan/genqlient
// For programmatic access, see the "generate" package, below. For
// user documentation, see github.com/Khan/genqlient.
package main package main
import ( import (