-
What I try to do? Why I want to do this? Steps required (probably?)
Here is the interface of my business logic: package behaviour
import "account/component/structure"
type AccountService interface {
Register(email string, password string) (structure.Session, error)
VerifyEmail(email string, emailVerificationCode string) error
DoesAccountExist(email string) bool
Login(email string, password string) (structure.Session, error)
IssueAccessToken(key string) (string, error)
GetAllSessions(key string) ([]structure.Session, error)
LogoutSession(key string, id int) error
} In goadesign I would like to call my business logic like this: session, err := service.Register("[email protected]", "super-secure-password") And then map the credential attributes of goa to strings and session struct to the goadesign types (pseudo code): var CredentialType = Type("Credential", func() {
Attribute("email", func() {
MinLength(3)
}),
Attribute("password", func() {
MinLength(8)
})
Required("email", "password")
})
var _ = Service("account", func() {
Description("Account service manages user accounts")
Method("register", func() {
Payload(CredentialType)
Result(func(credentialType) {
session, _ := service.Register(credentialType.Email, credentialType.Password)
return session
})
})
Files("/openapi.json", "./gen/http/openapi.json")
}) Question: Is this possible? How can I achieve the above with preferably minimal amount of code? Disclaimer: I am new to goadesign so please forgive me for stupid questions or insufficient knowledge. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Hello, Goa takes care of generating the transport layer and endpoint code and then lets you inject the actual business logic (which Goa cannot generate since it has no knowledge of what it should be). Reusing the diagram from https://goa.design/implement/implementing/:
Goa generates the code for all the boxes except the right-most one. For the business logic It generates an interface and expects the user to provide its implementation - that's how the business logic is injected, see the basic calc example for what that interface looks like. So to answer the question the idea would be to provide an adapter that maps the existing business logic to the interface expected by the generated code. Just as an example: type AccountServiceAdapter struct {
*AccountService
}
// This function implements the interface generated by Goa and calls the underlying business logic.
func (as *AccountServiceAdapter) Register(ctx context.Context, p *accountsvc.RegisterPayload) (*accountsvc.RegisterResult, error) {
session, err := as.AccountService.Register(p.email, p.password)
if err != nil {
return nil, err // may want to map to design errors to produce correct transport code (HTTP status / gRPC code)
}
return &accountsvc.RegisterResult{Session: session}, nil
}
// .... Again above is just one way to do it for illustration. |
Beta Was this translation helpful? Give feedback.
Hello,
Goa takes care of generating the transport layer and endpoint code and then lets you inject the actual business logic (which Goa cannot generate since it has no knowledge of what it should be). Reusing the diagram from https://goa.design/implement/implementing/: