Skip to content

Commit

Permalink
improve tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hgiasac committed Feb 25, 2024
1 parent cccfe7c commit 30a1b9d
Show file tree
Hide file tree
Showing 15 changed files with 245 additions and 74 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ lint:

.PHONY: build-codegen
build-codegen:
go build -o _output/ndc-go-sdk ./codegen
go build -o _output/ndc-go-sdk ./cmd/ndc-go-sdk
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ All functions of the Connector interface are analogous to their Rust counterpart
- Authentication
- Observability with OpenTelemetry and Prometheus

## Quick start

Checkout the [generation tool](cmd/ndc-go-sdk) to quickly setup and develop data connectors.

## Using this SDK

The SDK exports a `Start` function, which takes a `connector` object, that is an object that implements the `Connector` interface defined in [connector/types.go](connector/types.go)
Expand Down
59 changes: 27 additions & 32 deletions cmd/ndc-go-sdk/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@ import (
_ "embed"
"encoding/json"
"fmt"
"io"
"os"
"path"
"strings"
"text/template"
)

//go:embed templates/connector/connector.go.tmpl
var connectorTemplate string

const (
connectorOutputFile = "connector.generated.go"
)
Expand All @@ -32,11 +29,6 @@ func parseAndGenerateConnector(basePath string, directories []string, moduleName
}

func generateConnector(rawSchema *RawConnectorSchema, srcPath string, moduleName string) error {
fileTemplate, err := template.New(connectorOutputFile).Parse(connectorTemplate)
if err != nil {
return err
}

// generate schema.generated.json
schemaBytes, err := json.MarshalIndent(rawSchema.Schema(), "", " ")
if err != nil {
Expand All @@ -48,10 +40,6 @@ func generateConnector(rawSchema *RawConnectorSchema, srcPath string, moduleName
return err
}

importLines := []string{}
for importPath := range rawSchema.Imports {
importLines = append(importLines, fmt.Sprintf(`"%s"`, importPath))
}
targetPath := path.Join(srcPath, connectorOutputFile)
f, err := os.Create(targetPath)
if err != nil {
Expand All @@ -62,16 +50,25 @@ func generateConnector(rawSchema *RawConnectorSchema, srcPath string, moduleName
}()

w := bufio.NewWriter(f)
err = fileTemplate.Execute(w, map[string]any{
defer func() {
_ = w.Flush()
}()

return genConnectorCodeFromTemplate(w, moduleName, rawSchema)
}

func genConnectorCodeFromTemplate(w io.Writer, moduleName string, rawSchema *RawConnectorSchema) error {
importLines := []string{}
for importPath := range rawSchema.Imports {
importLines = append(importLines, fmt.Sprintf(`"%s"`, importPath))
}

return connectorTemplate.Execute(w, map[string]any{
"Imports": strings.Join(importLines, "\n"),
"Module": moduleName,
"Queries": genConnectorFunctions(rawSchema),
"Procedures": genConnectorProcedures(rawSchema),
})
if err != nil {
return err
}
return w.Flush()
}

func genConnectorFunctions(rawSchema *RawConnectorSchema) string {
Expand All @@ -85,15 +82,14 @@ func genConnectorFunctions(rawSchema *RawConnectorSchema) string {
var argumentParamStr string
if fn.ArgumentsType != "" {
argumentStr = fmt.Sprintf(`args, err := schema.ResolveArguments[%s.%s](request.Arguments, variables)
if err != nil {
return nil, schema.BadRequestError("failed to resolve arguments", map[string]any{
"cause": err.Error(),
})
}`, fn.PackageName, fn.ArgumentsType)
if err != nil {
return nil, schema.BadRequestError("failed to resolve arguments", map[string]any{
"cause": err.Error(),
})
}`, fn.PackageName, fn.ArgumentsType)
argumentParamStr = ", args"
}
fnCase := fmt.Sprintf(`
case "%s":
fnCase := fmt.Sprintf(` case "%s":
%s
return %s.%s(ctx, state%s)`, fn.Name, argumentStr, fn.PackageName, fn.OriginName, argumentParamStr)
functionCases = append(functionCases, fnCase)
Expand All @@ -113,15 +109,14 @@ func genConnectorProcedures(rawSchema *RawConnectorSchema) string {
var argumentParamStr string
if fn.ArgumentsType != "" {
argumentStr = fmt.Sprintf(`var args %s.%s
if err := json.Unmarshal(operation.Arguments, &args); err != nil {
return nil, schema.BadRequestError("failed to decode arguments", map[string]any{
"cause": err.Error(),
})
}`, fn.PackageName, fn.ArgumentsType)
if err := json.Unmarshal(operation.Arguments, &args); err != nil {
return nil, schema.BadRequestError("failed to decode arguments", map[string]any{
"cause": err.Error(),
})
}`, fn.PackageName, fn.ArgumentsType)
argumentParamStr = ", &args"
}
fnCase := fmt.Sprintf(`
case "%s":
fnCase := fmt.Sprintf(` case "%s":
%s
rawResult, err = %s.%s(ctx, state%s)`, fn.Name, argumentStr, fn.PackageName, fn.OriginName, argumentParamStr)
cases = append(cases, fnCase)
Expand Down
48 changes: 27 additions & 21 deletions cmd/ndc-go-sdk/schema_test.go → cmd/ndc-go-sdk/connector_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package main

import (
"bufio"
"bytes"
"embed"
"encoding/json"
"go/ast"
"go/parser"
"go/token"
"io/fs"
"regexp"
"testing"

"github.com/hasura/ndc-sdk-go/schema"
Expand All @@ -19,16 +22,23 @@ var basicSource embed.FS
//go:embed testdata/basic/schema.json
var basicSchemaBytes []byte

func TestParseCodesToNdcSchema(t *testing.T) {
//go:embed testdata/basic/expected/connector.go.tmpl
var basicExpectedContent string

func TestConnectorGeneration(t *testing.T) {
trimNewLinesRegexp := regexp.MustCompile(`\n\t*\n`)

testCases := []struct {
Name string
Src embed.FS
Schema []byte
Name string
Src embed.FS
Schema []byte
Generated string
}{
{
Name: "basic",
Src: basicSource,
Schema: basicSchemaBytes,
Name: "basic",
Src: basicSource,
Schema: basicSchemaBytes,
Generated: basicExpectedContent,
},
}

Expand Down Expand Up @@ -63,29 +73,25 @@ func TestParseCodesToNdcSchema(t *testing.T) {

return nil
})

if err != nil {
t.Errorf("failed to read source code: %s", err)
t.FailNow()
}

if err := schemaParser.checkAndParseRawSchemaFromAstFiles(rawSchema); err != nil {
t.Errorf("failed to parse raw schema: %s", err)
t.FailNow()
}
assert.NoError(t, err)
assert.NoError(t, schemaParser.checkAndParseRawSchemaFromAstFiles(rawSchema))

schemaOutput := rawSchema.Schema()
var schema schema.SchemaResponse
if err := json.Unmarshal(basicSchemaBytes, &schema); err != nil {
t.Errorf("failed to decode expected schema: %s", err)
t.FailNow()
}
assert.NoError(t, json.Unmarshal(basicSchemaBytes, &schema))

assert.Equal(t, schema.Collections, schemaOutput.Collections)
assert.Equal(t, schema.Functions, schemaOutput.Functions)
assert.Equal(t, schema.Procedures, schemaOutput.Procedures)
assert.Equal(t, schema.ScalarTypes, schemaOutput.ScalarTypes)
assert.Equal(t, schema.ObjectTypes, schemaOutput.ObjectTypes)

var buf bytes.Buffer
w := bufio.NewWriter(&buf)
assert.NoError(t, genConnectorCodeFromTemplate(w, "hasura.dev/connector", rawSchema))
w.Flush()
outputText := trimNewLinesRegexp.ReplaceAllString(string(buf.String()), "\n")
assert.Equal(t, basicExpectedContent, outputText)
})
}
}
4 changes: 1 addition & 3 deletions cmd/ndc-go-sdk/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,9 +464,7 @@ func (sp *SchemaParser) parseTypeInfoFromComments(typeName string, pos token.Pos
if !typeInfo.IsScalar {
// fallback to parse scalar from type name with Scalar prefix
matches := ndcScalarNameRegex.FindStringSubmatch(typeName)
matchesLen := len(matches)
log.Printf("%s: scalar matches: %v", typeName, matches)
if matchesLen > 1 {
if len(matches) > 1 {
typeInfo.IsScalar = true
typeInfo.SchemaName = matches[1]
typeInfo.Schema = schema.NewNamedType(matches[1])
Expand Down
15 changes: 14 additions & 1 deletion cmd/ndc-go-sdk/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,25 @@ import (
"golang.org/x/mod/modfile"
)

//go:embed templates/new
//go:embed all:* templates/new
var initTemplateFS embed.FS

//go:embed templates/connector/connector.go.tmpl
var connectorTemplateStr string
var connectorTemplate *template.Template

const (
templateNewPath = "templates/new"
)

func init() {
var err error
connectorTemplate, err = template.New(connectorOutputFile).Parse(connectorTemplateStr)
if err != nil {
panic(fmt.Errorf("failed to parse connector template: %s", err))
}
}

func generateNewProject(name string, moduleName string, srcPath string) error {
if srcPath == "" {
p, err := os.Getwd()
Expand Down Expand Up @@ -57,6 +69,7 @@ func generateNewProjectFiles(name string, moduleName string, srcPath string) err
return err
}

log.Info().Msgf("filePath: %s", filePath)
if filePath == templateNewPath {
return nil
}
Expand Down
12 changes: 12 additions & 0 deletions cmd/ndc-go-sdk/template_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestGenerateNewProject(t *testing.T) {
tempDir := t.TempDir()
assert.NoError(t, generateNewProject("test", "hasura.dev/connector", tempDir))
}
4 changes: 2 additions & 2 deletions cmd/ndc-go-sdk/templates/connector/connector.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (c *Connector) Mutation(ctx context.Context, configuration *types.Configura
func execQuery(ctx context.Context, configuration *types.Configuration, state *types.State, request *schema.QueryRequest, variables map[string]any) (any, error) {

switch request.Collection {
{{.Queries}}
{{.Queries}}
default:
return nil, schema.BadRequestError(fmt.Sprintf("unsupported query: %s", request.Collection), nil)
}
Expand All @@ -96,7 +96,7 @@ func execProcedure(ctx context.Context, configuration *types.Configuration, stat
var rawResult any
var err error
switch operation.Name {
{{.Procedures}}
{{.Procedures}}
default:
return nil, schema.BadRequestError(fmt.Sprintf("unsupported procedure operation: %s", operation.Name), nil)
}
Expand Down
10 changes: 0 additions & 10 deletions cmd/ndc-go-sdk/templates/new/README.md

This file was deleted.

11 changes: 11 additions & 0 deletions cmd/ndc-go-sdk/templates/new/README.md.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# {{.Name}} Connector

## Get started

Start the connector server at http://localhost:8080

```go
go run . serve
```

See [NDC Go SDK](https://github.com/hasura/ndc-sdk-go) for more information and [the generation tool](https://github.com/hasura/ndc-sdk-go/tree/main/cmd/ndc-go-sdk) for command documentation.
2 changes: 2 additions & 0 deletions cmd/ndc-go-sdk/templates/new/types/connector.go.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package types

// Configuration contains required settings for the connector.
type Configuration struct{}

// State is the global state which is shared for every connector request.
type State struct{}
Loading

0 comments on commit 30a1b9d

Please sign in to comment.