Skip to content

Commit

Permalink
Clean up godoc (Khan#82)
Browse files Browse the repository at this point in the history
## 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 Khan#25.

Issue: Khan#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: Khan#82
  • Loading branch information
benjaminjkraft authored Sep 10, 2021
1 parent dc38360 commit d41cf63
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 36 deletions.
36 changes: 21 additions & 15 deletions generate/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"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 {
// The filename with the GraphQL schema (in SDL format); defaults to
// schema.graphql
Expand Down Expand Up @@ -100,8 +104,9 @@ type Config struct {
// them at your own risk!
AllowBrokenFeatures bool `yaml:"allow_broken_features"`

// Set automatically to the filename of the config file itself.
configFilename string
// The directory of the config-file (relative to which all the other paths
// are resolved). Set by ValidateAndFillDefaults.
baseDir string
}

// A TypeBinding represents a Go type to which genqlient will bind a particular
Expand Down Expand Up @@ -134,22 +139,21 @@ type TypeBinding struct {
ExpectExactFields string `yaml:"expect_exact_fields"`
}

// baseDir returns the directory of the config-file (relative to which
// all the other paths are resolved).
func (c *Config) baseDir() string {
return filepath.Dir(c.configFilename)
}

func (c *Config) ValidateAndFillDefaults(configFilename string) error {
c.configFilename = configFilename
// ValidateAndFillDefaults ensures that the configuration is valid, and fills
// in any options that were unspecified.
//
// 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 {
c.baseDir = baseDir
// 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 {
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 != "" {
c.ExportOperations = filepath.Join(c.baseDir(), c.ExportOperations)
c.ExportOperations = filepath.Join(baseDir, c.ExportOperations)
}

if c.ContextType == "" {
Expand All @@ -173,6 +177,8 @@ func (c *Config) ValidateAndFillDefaults(configFilename string) error {
return nil
}

// ReadAndValidateConfig reads the configuration from the given file, validates
// it, and returns it.
func ReadAndValidateConfig(filename string) (*Config, error) {
text, err := ioutil.ReadFile(filename)
if err != nil {
Expand All @@ -185,7 +191,7 @@ func ReadAndValidateConfig(filename string) (*Config, error) {
return nil, errorf(nil, "invalid config file %v: %v", filename, err)
}

err = config.ValidateAndFillDefaults(filename)
err = config.ValidateAndFillDefaults(filepath.Dir(filename))
if err != nil {
return nil, errorf(nil, "invalid config file %v: %v", filename, err)
}
Expand Down
11 changes: 6 additions & 5 deletions generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,12 @@ func (g *generator) addOperation(op *ast.OperationDefinition) error {
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
// wish to manage the config-reading (ReadAndValidateConfig) and file-writing
// on their own. (Those are wired in by Main.)
// See Config for more on creating a configuration. The return value is a map
// from filename to the generated file-content (e.g. Go source). Callers who
// don't want to manage reading and writing the files should call Main.
func Generate(config *Config) (map[string][]byte, error) {
// 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
Expand All @@ -343,7 +344,7 @@ func Generate(config *Config) (map[string][]byte, error) {
return nil, err
}

document, err := getAndValidateQueries(config.baseDir(), config.Operations, schema)
document, err := getAndValidateQueries(config.baseDir, config.Operations, schema)
if err != nil {
return nil, err
}
Expand Down
30 changes: 15 additions & 15 deletions generate/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,43 +145,43 @@ func defaultConfig(t *testing.T) *Config {
// configurations. It uses snapshots, just like TestGenerate.
func TestGenerateWithConfig(t *testing.T) {
tests := []struct {
name string
fakeConfigFilename string
config *Config // omits Schema and Operations, set below.
name string
baseDir string // relative to dataDir
config *Config // omits Schema and Operations, set below.
}{
{"DefaultConfig", "genqlient.yaml", defaultConfig(t)},
{"Subpackage", "genqlient.yaml", &Config{
{"DefaultConfig", "", defaultConfig(t)},
{"Subpackage", "", &Config{
Generated: "mypkg/myfile.go",
}},
{"SubpackageConfig", "mypkg/genqlient.yaml", &Config{
{"SubpackageConfig", "mypkg", &Config{
Generated: "myfile.go", // (relative to genqlient.yaml)
}},
{"PackageName", "genqlient.yaml", &Config{
{"PackageName", "", &Config{
Generated: "myfile.go",
Package: "mypkg",
}},
{"ExportOperations", "genqlient.yaml", &Config{
{"ExportOperations", "", &Config{
Generated: "generated.go",
ExportOperations: "operations.json",
}},
{"CustomContext", "genqlient.yaml", &Config{
{"CustomContext", "", &Config{
Generated: "generated.go",
ContextType: "github.com/Khan/genqlient/internal/testutil.MyContext",
}},
{"NoContext", "genqlient.yaml", &Config{
{"NoContext", "", &Config{
Generated: "generated.go",
ContextType: "-",
}},
{"ClientGetter", "genqlient.yaml", &Config{
{"ClientGetter", "", &Config{
Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromContext",
}},
{"ClientGetterCustomContext", "genqlient.yaml", &Config{
{"ClientGetterCustomContext", "", &Config{
Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromMyContext",
ContextType: "github.com/Khan/genqlient/internal/testutil.MyContext",
}},
{"ClientGetterNoContext", "genqlient.yaml", &Config{
{"ClientGetterNoContext", "", &Config{
Generated: "generated.go",
ClientGetter: "github.com/Khan/genqlient/internal/testutil.GetClientFromNowhere",
ContextType: "-",
Expand All @@ -192,9 +192,9 @@ func TestGenerateWithConfig(t *testing.T) {

for _, test := range tests {
config := test.config
baseDir := filepath.Join(dataDir, test.baseDir)
t.Run(test.name, func(t *testing.T) {
err := config.ValidateAndFillDefaults(
filepath.Join(dataDir, test.fakeConfigFilename))
err := config.ValidateAndFillDefaults(baseDir)
config.Schema = filepath.Join(dataDir, "schema.graphql")
config.Operations = []string{filepath.Join(dataDir, sourceFilename)}
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions generate/main.go
Original file line number Diff line number Diff line change
@@ -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

import (
Expand Down Expand Up @@ -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() {
exitIfError := func(err error) {
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -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

import (
Expand Down

0 comments on commit d41cf63

Please sign in to comment.