Skip to content

Commit

Permalink
codegen: add nested field selection to the command context (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
hgiasac authored Jan 6, 2025
1 parent ae15d34 commit 6486aa7
Show file tree
Hide file tree
Showing 21 changed files with 304 additions and 42 deletions.
7 changes: 3 additions & 4 deletions cmd/hasura-ndc-go/command/internal/connector_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ func (chb connectorHandlerBuilder) Render() {
bs.imports["github.com/hasura/ndc-sdk-go/connector"] = ""
bs.imports["github.com/hasura/ndc-sdk-go/schema"] = ""
bs.imports["go.opentelemetry.io/otel/trace"] = ""
if len(chb.Functions) > 0 || len(chb.Procedures) > 0 {
bs.imports[packageSDKUtils] = ""
}
bs.imports[packageSDKUtils] = ""

if chb.RawSchema.StateType != nil && bs.packagePath != chb.RawSchema.StateType.PackagePath {
bs.imports[chb.RawSchema.StateType.PackagePath] = ""
Expand Down Expand Up @@ -99,7 +97,7 @@ func (dch DataConnectorHandler) Query(ctx context.Context, state *`)
return nil, schema.UnprocessableContentError(err.Error(), nil)
}
result, err := dch.execQuery(ctx, state, request, queryFields, rawArgs)
result, err := dch.execQuery(context.WithValue(ctx, utils.CommandSelectionFieldKey, queryFields), state, request, queryFields, rawArgs)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -208,6 +206,7 @@ func (dch DataConnectorHandler) Mutation(ctx context.Context, state *`)
_, _ = sb.WriteString(`, operation *schema.MutationOperation) (schema.MutationOperationResults, error) {
span := trace.SpanFromContext(ctx)
logger := connector.GetLogger(ctx)
ctx = context.WithValue(ctx, utils.CommandSelectionFieldKey, operation.Fields)
connector_addSpanEvent(span, logger, "validate_request", map[string]any{
"operations_name": operation.Name,
})
Expand Down
35 changes: 16 additions & 19 deletions cmd/hasura-ndc-go/command/internal/connector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,28 +116,25 @@ func TestConnectorGeneration(t *testing.T) {
assert.NilError(t, os.Chdir(".."))

for _, td := range tc.Directories {
expectedFunctionTypesBytes, err := os.ReadFile(path.Join("expected", "functions.go.tmpl"))
if err == nil {
var generatedPath string
for _, globPath := range []string{filepath.Join("source", td, "types.generated.go"), filepath.Join("source", td, "**", "types.generated.go")} {
goFiles, err := filepath.Glob(globPath)
for _, globPath := range []string{filepath.Join("source", td, "types.generated.go"), filepath.Join("source", td, "**", "types.generated.go")} {
goFiles, err := filepath.Glob(globPath)
assert.NilError(t, err)

for _, goFile := range goFiles {
log.Println("file", goFile)

expectedDir := filepath.Dir(strings.Replace(goFile, "source/", "expected/", -1))

expectedFunctionTypesBytes, err := os.ReadFile(filepath.Join(expectedDir, "types.generated.go.tmpl"))
assert.NilError(t, err)
log.Println(globPath, goFiles)
if len(goFiles) > 0 {
generatedPath = goFiles[0]

break
}
}
functionTypesBytes, err := os.ReadFile(goFile)
assert.NilError(t, err)

assert.Assert(t, generatedPath != "")
functionTypesBytes, err := os.ReadFile(generatedPath)
assert.NilError(t, err)
expected := formatTextContent(string(expectedFunctionTypesBytes))
reality := formatTextContent(string(functionTypesBytes))
assert.Equal(t, expected, reality)
} else if !os.IsNotExist(err) {
assert.NilError(t, err)
expected := formatTextContent(string(expectedFunctionTypesBytes))
reality := formatTextContent(string(functionTypesBytes))
assert.Equal(t, expected, reality)
}
}
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1203,7 +1203,7 @@ func (dch DataConnectorHandler) Query(ctx context.Context, state *types.State, r
return nil, schema.UnprocessableContentError(err.Error(), nil)
}

result, err := dch.execQuery(ctx, state, request, queryFields, rawArgs)
result, err := dch.execQuery(context.WithValue(ctx, utils.CommandSelectionFieldKey, queryFields), state, request, queryFields, rawArgs)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1371,6 +1371,7 @@ func (dch DataConnectorHandler) MutationExists(name string) bool {
func (dch DataConnectorHandler) Mutation(ctx context.Context, state *types.State, operation *schema.MutationOperation) (schema.MutationOperationResults, error) {
span := trace.SpanFromContext(ctx)
logger := connector.GetLogger(ctx)
ctx = context.WithValue(ctx, utils.CommandSelectionFieldKey, operation.Fields)
connector_addSpanEvent(span, logger, "validate_request", map[string]any{
"operations_name": operation.Name,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ go 1.21
require (
github.com/google/uuid v1.6.0
github.com/hasura/ndc-sdk-go v1.4.1
go.opentelemetry.io/otel v1.29.0
go.opentelemetry.io/otel/trace v1.29.0
golang.org/x/sync v0.10.0
)

require (
Expand All @@ -24,7 +27,6 @@ require (
github.com/prometheus/procfs v0.15.1 // indirect
go.opentelemetry.io/contrib/bridges/otelslog v0.4.0 // indirect
go.opentelemetry.io/contrib/propagators/b3 v1.29.0 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.5.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.5.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect
Expand All @@ -38,7 +40,6 @@ require (
go.opentelemetry.io/otel/sdk v1.29.0 // indirect
go.opentelemetry.io/otel/sdk/log v0.5.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect
go.opentelemetry.io/otel/trace v1.29.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.28.0 // indirect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ module github.com/hasura/ndc-codegen-empty-test

go 1.21

require github.com/hasura/ndc-sdk-go v1.4.1
require (
github.com/hasura/ndc-sdk-go v1.4.1
go.opentelemetry.io/otel v1.29.0
golang.org/x/sync v0.10.0
)

require (
github.com/alecthomas/kong v1.6.0 // indirect
Expand All @@ -22,7 +26,6 @@ require (
github.com/prometheus/procfs v0.15.1 // indirect
go.opentelemetry.io/contrib/bridges/otelslog v0.4.0 // indirect
go.opentelemetry.io/contrib/propagators/b3 v1.29.0 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.5.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.5.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Code generated by github.com/hasura/ndc-sdk-go/cmd/hasura-ndc-go, DO NOT EDIT.
package function
import (
"context"
"github.com/hasura/ndc-codegen-function-only-test/types"
"github.com/hasura/ndc-sdk-go/connector"
"github.com/hasura/ndc-sdk-go/schema"
"github.com/hasura/ndc-sdk-go/utils"
"go.opentelemetry.io/otel/trace"
"log/slog"
"slices"
)

// ToMap encodes the struct to a value map
func (j SimpleResult) ToMap() map[string]any {
r := make(map[string]any)
r["reply"] = j.Reply

return r
}
// DataConnectorHandler implements the data connector handler
type DataConnectorHandler struct{}

// QueryExists check if the query name exists
func (dch DataConnectorHandler) QueryExists(name string) bool {
return slices.Contains(enumValues_FunctionName, name)
}
func (dch DataConnectorHandler) Query(ctx context.Context, state *types.State, request *schema.QueryRequest, rawArgs map[string]any) (*schema.RowSet, error) {
if !dch.QueryExists(request.Collection) {
return nil, utils.ErrHandlerNotfound
}
queryFields, err := utils.EvalFunctionSelectionFieldValue(request)
if err != nil {
return nil, schema.UnprocessableContentError(err.Error(), nil)
}

result, err := dch.execQuery(context.WithValue(ctx, utils.CommandSelectionFieldKey, queryFields), state, request, queryFields, rawArgs)
if err != nil {
return nil, err
}

return &schema.RowSet{
Aggregates: schema.RowSetAggregates{},
Rows: []map[string]any{
{
"__value": result,
},
},
}, nil
}

func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.State, request *schema.QueryRequest, queryFields schema.NestedField, rawArgs map[string]any) (any, error) {
span := trace.SpanFromContext(ctx)
logger := connector.GetLogger(ctx)
switch request.Collection {
case "simpleObject":

selection, err := queryFields.AsObject()
if err != nil {
return nil, schema.UnprocessableContentError("the selection field type must be object", map[string]any{
"cause": err.Error(),
})
}
rawResult, err := FunctionSimpleObject(ctx, state)

if err != nil {
return nil, err
}

connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{
"raw_result": rawResult,
})
result, err := utils.EvalNestedColumnObject(selection, rawResult)
if err != nil {
return nil, err
}
return result, nil

default:
return nil, utils.ErrHandlerNotfound
}
}
var enumValues_FunctionName = []string{"simpleObject"}
func connector_addSpanEvent(span trace.Span, logger *slog.Logger, name string, data map[string]any, options ...trace.EventOption) {
logger.Debug(name, slog.Any("data", data))
attrs := utils.DebugJSONAttributes(data, utils.IsDebug(logger))
span.AddEvent(name, append(options, trace.WithAttributes(attrs...))...)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Code generated by github.com/hasura/ndc-sdk-go/cmd/hasura-ndc-go, DO NOT EDIT.
package hello
import (
"context"
"github.com/hasura/ndc-codegen-function-only-test/types"
"github.com/hasura/ndc-sdk-go/connector"
"github.com/hasura/ndc-sdk-go/schema"
"github.com/hasura/ndc-sdk-go/utils"
"go.opentelemetry.io/otel/trace"
"log/slog"
"slices"
)

// DataConnectorHandler implements the data connector handler
type DataConnectorHandler struct{}

// QueryExists check if the query name exists
func (dch DataConnectorHandler) QueryExists(name string) bool {
return slices.Contains(enumValues_FunctionName, name)
}
func (dch DataConnectorHandler) Query(ctx context.Context, state *types.State, request *schema.QueryRequest, rawArgs map[string]any) (*schema.RowSet, error) {
if !dch.QueryExists(request.Collection) {
return nil, utils.ErrHandlerNotfound
}
queryFields, err := utils.EvalFunctionSelectionFieldValue(request)
if err != nil {
return nil, schema.UnprocessableContentError(err.Error(), nil)
}

result, err := dch.execQuery(context.WithValue(ctx, utils.CommandSelectionFieldKey, queryFields), state, request, queryFields, rawArgs)
if err != nil {
return nil, err
}

return &schema.RowSet{
Aggregates: schema.RowSetAggregates{},
Rows: []map[string]any{
{
"__value": result,
},
},
}, nil
}

func (dch DataConnectorHandler) execQuery(ctx context.Context, state *types.State, request *schema.QueryRequest, queryFields schema.NestedField, rawArgs map[string]any) (any, error) {
span := trace.SpanFromContext(ctx)
logger := connector.GetLogger(ctx)
switch request.Collection {
case "hello":

if len(queryFields) > 0 {
return nil, schema.UnprocessableContentError("cannot evaluate selection fields for scalar", nil)
}
return FunctionHello(ctx, state)

default:
return nil, utils.ErrHandlerNotfound
}
}
var enumValues_FunctionName = []string{"hello"}
func connector_addSpanEvent(span trace.Span, logger *slog.Logger, name string, data map[string]any, options ...trace.EventOption) {
logger.Debug(name, slog.Any("data", data))
attrs := utils.DebugJSONAttributes(data, utils.IsDebug(logger))
span.AddEvent(name, append(options, trace.WithAttributes(attrs...))...)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Code generated by github.com/hasura/ndc-sdk-go/cmd/hasura-ndc-go, DO NOT EDIT.
package procedure
import (
"context"
"github.com/hasura/ndc-codegen-function-only-test/types"
"github.com/hasura/ndc-sdk-go/connector"
"github.com/hasura/ndc-sdk-go/schema"
"github.com/hasura/ndc-sdk-go/utils"
"go.opentelemetry.io/otel/trace"
"log/slog"
"slices"
)

// DataConnectorHandler implements the data connector handler
type DataConnectorHandler struct{}

// MutationExists check if the mutation name exists
func (dch DataConnectorHandler) MutationExists(name string) bool {
return slices.Contains(enumValues_ProcedureName, name)
}
func (dch DataConnectorHandler) Mutation(ctx context.Context, state *types.State, operation *schema.MutationOperation) (schema.MutationOperationResults, error) {
span := trace.SpanFromContext(ctx)
logger := connector.GetLogger(ctx)
ctx = context.WithValue(ctx, utils.CommandSelectionFieldKey, operation.Fields)
connector_addSpanEvent(span, logger, "validate_request", map[string]any{
"operations_name": operation.Name,
})

switch operation.Name {
case "createDemo":

selection, err := operation.Fields.AsObject()
if err != nil {
return nil, schema.UnprocessableContentError("the selection field type must be object", map[string]any{
"cause": err.Error(),
})
}
span.AddEvent("execute_procedure")
rawResult, err := ProcedureCreateDemo(ctx, state)

if err != nil {
return nil, err
}

if rawResult == nil {
return schema.NewProcedureResult(nil).Encode(), nil
}
connector_addSpanEvent(span, logger, "evaluate_response_selection", map[string]any{
"raw_result": rawResult,
})
result, err := utils.EvalNestedColumnObject(selection, rawResult)

if err != nil {
return nil, err
}
return schema.NewProcedureResult(result).Encode(), nil

default:
return nil, utils.ErrHandlerNotfound
}
}
var enumValues_ProcedureName = []string{"createDemo"}
func connector_addSpanEvent(span trace.Span, logger *slog.Logger, name string, data map[string]any, options ...trace.EventOption) {
logger.Debug(name, slog.Any("data", data))
attrs := utils.DebugJSONAttributes(data, utils.IsDebug(logger))
span.AddEvent(name, append(options, trace.WithAttributes(attrs...))...)
}
Loading

0 comments on commit 6486aa7

Please sign in to comment.