diff --git a/README.md b/README.md index 8f211c04..6fef2c38 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,9 @@ Before contributing, all linting and tests must pass. Tests can be run directly # Only integration tests $ make test-integration +*Note:* You'll need to update `testdata/schema.json` to the latest GraphQL schema for tests to run +correctly. + ### Commit Messages Using the following format for commit messages allows for auto-generation of diff --git a/configs/tutone.yml b/configs/tutone.yml index bca32bc5..7f46dcc7 100644 --- a/configs/tutone.yml +++ b/configs/tutone.yml @@ -25,6 +25,7 @@ auth: packages: - name: nerdgraph path: pkg/nerdgraph + import_path: github.com/newrelic/newrelic-client-go/pkg/nerdgraph generators: - typegen mutations: @@ -35,6 +36,28 @@ packages: field_type_override: string skip_type_create: true + - name: cloud + path: pkg/cloud + imports: + - github.com/newrelic/newrelic-client-go/internal/serialization + - encoding/json + - fmt + generators: + - typegen + - nerdgraphclient + queries: + - path: ["actor", "cloud"] + endpoints: + - name: linkedAccounts + maxQueryFieldDepth: 2 + include_nullable: true + mutations: + - name: cloudConfigureIntegration + - name: cloudDisableIntegration + - name: cloudLinkAccount + - name: cloudRenameAccount + - name: cloudUnlinkAccount + generators: - name: typegen fileName: "types.go" diff --git a/internal/config/config.go b/internal/config/config.go index f5692831..dc17ad3b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -46,6 +46,8 @@ type PackageConfig struct { Name string `yaml:"name,omitempty"` // Path is the relative path within the project. Path string `yaml:"path,omitempty"` + // ImportPath is the full path used for importing this package into a Go project + ImportPath string `yaml:"import_path,omitempty"` // Types is a list of Type configurations to include in the package. Types []TypeConfig `yaml:"types,omitempty"` // Mutations is a list of Method configurations to include in the package. @@ -116,7 +118,8 @@ type MutationConfig struct { type EndpointConfig struct { Name string `yaml:"name,omitempty"` - MaxQueryFieldDepth int `yaml:"maxQueryFieldDepth,omitempty"` + MaxQueryFieldDepth int `yaml:"max_query_field_depth,omitempty"` + IncludeNullable bool `yaml:"include_nullable,omitempty"` } // TypeConfig is the information about which types to render and any data specific to handling of the type. diff --git a/internal/config/config_test.go b/internal/config/config_test.go index ad7967e8..60ac8d5f 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -30,18 +30,41 @@ func TestLoadConfig(t *testing.T) { }, Packages: []PackageConfig{ { - Name: "alerts", - Path: "pkg/alerts", + Name: "alerts", + Path: "pkg/alerts", + ImportPath: "github.com/newrelic/newrelic-client-go/pkg/alerts", Types: []TypeConfig{ { Name: "AlertsMutingRuleConditionInput", - }, { + }, + { Name: "ID", FieldTypeOverride: "string", SkipTypeCreate: true, }, + { + Name: "InterfaceImplementation", + InterfaceMethods: []string{ + "Get() string", + }, + }, }, Generators: []string{"typegen"}, + Queries: []Query{ + { + Path: []string{ + "actor", + "cloud", + }, + Endpoints: []EndpointConfig{ + { + Name: "linkedAccounts", + MaxQueryFieldDepth: 2, + IncludeNullable: true, + }, + }, + }, + }, }, }, Generators: []GeneratorConfig{ diff --git a/internal/schema/schema.go b/internal/schema/schema.go index 1d2b9d50..3f3d6435 100644 --- a/internal/schema/schema.go +++ b/internal/schema/schema.go @@ -299,7 +299,7 @@ func (s *Schema) BuildQueryArgsForEndpoint(t *Type, fields []string, includeNull } // GetQueryStringForEndpoint packs a nerdgraph query header and footer around the set of query fields for a given type name and endpoint. -func (s *Schema) GetQueryStringForEndpoint(typePath []*Type, fieldPath []string, endpoint string, depth int) string { +func (s *Schema) GetQueryStringForEndpoint(typePath []*Type, fieldPath []string, endpoint string, depth int, includeNullable bool) string { // We use the final type in the type path so that we can locate the field on // this type by the same name of the receveid endpoint. Without this @@ -344,7 +344,7 @@ func (s *Schema) GetQueryStringForEndpoint(typePath []*Type, fieldPath []string, // Append to QueryArgs and EndpointArgs only after the parent field // requirements have been added so that they are last. - args := s.BuildQueryArgsForEndpoint(t, []string{endpoint}, false) + args := s.BuildQueryArgsForEndpoint(t, []string{endpoint}, includeNullable) data.EndpointArgs = append(data.EndpointArgs, args...) // Append all the endpoint args to the query args data.QueryArgs = append(data.QueryArgs, data.EndpointArgs...) diff --git a/internal/schema/schema_test.go b/internal/schema/schema_test.go index 1a5f0b58..c7a3e914 100644 --- a/internal/schema/schema_test.go +++ b/internal/schema/schema_test.go @@ -168,30 +168,35 @@ func TestSchema_GetQueryStringForEndpoint(t *testing.T) { require.NoError(t, err) cases := map[string]struct { - Path []string - Field string - Depth int + Path []string + Field string + Depth int + Nullable bool }{ "entitySearch": { - Path: []string{"actor"}, - Field: "entitySearch", - Depth: 3, + Path: []string{"actor"}, + Field: "entitySearch", + Depth: 3, + Nullable: false, }, "entities": { Path: []string{"actor"}, Field: "entities", // Zero set here because we have the field coverage above with greater depth. Here we want to ensure that required arguments on the entities endpoint has the correct syntax. - Depth: 0, + Depth: 0, + Nullable: false, }, "linkedAccounts": { - Path: []string{"actor", "cloud"}, - Field: "linkedAccounts", - Depth: 2, + Path: []string{"actor", "cloud"}, + Field: "linkedAccounts", + Depth: 2, + Nullable: true, }, "policy": { - Path: []string{"actor", "account", "alerts"}, - Field: "policy", - Depth: 2, + Path: []string{"actor", "account", "alerts"}, + Field: "policy", + Depth: 2, + Nullable: false, }, } @@ -200,7 +205,7 @@ func TestSchema_GetQueryStringForEndpoint(t *testing.T) { typePath, err := s.LookupQueryTypesByFieldPath(tc.Path) require.NoError(t, err) - result := s.GetQueryStringForEndpoint(typePath, tc.Path, tc.Field, tc.Depth) + result := s.GetQueryStringForEndpoint(typePath, tc.Path, tc.Field, tc.Depth, tc.Nullable) // saveFixture(t, n, result) expected := loadFixture(t, n) assert.Equal(t, expected, result) diff --git a/internal/schema/testdata/TestSchema_GetQueryStringForEndpoint_linkedAccounts.txt b/internal/schema/testdata/TestSchema_GetQueryStringForEndpoint_linkedAccounts.txt index 2e3d5566..89f8d2e3 100644 --- a/internal/schema/testdata/TestSchema_GetQueryStringForEndpoint_linkedAccounts.txt +++ b/internal/schema/testdata/TestSchema_GetQueryStringForEndpoint_linkedAccounts.txt @@ -1,5 +1,7 @@ query( + $provider: String, ) { actor { cloud { linkedAccounts( + provider: $provider, ) { authLabel createdAt diff --git a/pkg/lang/golang.go b/pkg/lang/golang.go index 2870d289..de384241 100644 --- a/pkg/lang/golang.go +++ b/pkg/lang/golang.go @@ -187,7 +187,7 @@ func GenerateGoMethodQueriesForPackage(s *schema.Schema, genConfig *config.Gener method := goMethodForField(field, pkgConfig, inputFields) - method.QueryString = s.GetQueryStringForEndpoint(typePath, pkgQuery.Path, endpoint.Name, endpoint.MaxQueryFieldDepth) + method.QueryString = s.GetQueryStringForEndpoint(typePath, pkgQuery.Path, endpoint.Name, endpoint.MaxQueryFieldDepth, endpoint.IncludeNullable) method.ResponseObjectType = fmt.Sprintf("%sResponse", endpoint.Name) method.Signature.ReturnPath = returnPath @@ -353,7 +353,7 @@ func GenerateGoTypesForPackage(s *schema.Schema, genConfig *config.GeneratorConf } // Require at least one auto-generated method, allow others - yyy.Methods = make([]string, len(interfaceMethods)+1) + yyy.Methods = make([]string, 0, len(interfaceMethods)+1) yyy.Methods = append(yyy.Methods, "Implements"+t.GetName()+"()") yyy.Methods = append(yyy.Methods, interfaceMethods...) diff --git a/testdata/goodConfig_fixture.yml b/testdata/goodConfig_fixture.yml index 020906d7..814a57b9 100644 --- a/testdata/goodConfig_fixture.yml +++ b/testdata/goodConfig_fixture.yml @@ -9,13 +9,24 @@ auth: packages: - name: alerts path: pkg/alerts + import_path: "github.com/newrelic/newrelic-client-go/pkg/alerts" generators: - typegen + queries: + - path: ["actor", "cloud"] + endpoints: + - name: linkedAccounts + max_query_field_depth: 2 + include_nullable: true types: - name: AlertsMutingRuleConditionInput - name: ID field_type_override: string skip_type_create: true + - name: InterfaceImplementation + interface_methods: + - "Get() string" + generators: - name: typegen fileName: "types.go"