Documentation ¶
Overview ¶
Package apigen provides a generator which generates API clients and request/response types via specific execution environment such as curl.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidDefinition represents the error is caused by definition misconfiguration. ErrInvalidDefinition = errors.New("invalid definition") // ErrUnimplemented represents the provided definition contains unsupported things (such as HTTP method). ErrUnimplemented = errors.New("unimplemented") // ErrInternal represents an unexpected error has occurred internally. ErrInternal = errors.New("internal error") )
Functions ¶
func Generate ¶
func Generate(ctx context.Context, def *Definition, opts ...Option) error
Generate generates client interfaces, types for requests and responses based on the passed API definitions. If the API definition is invalid, Generate returns an error wrapping ErrInvalidDefinition.
Example ¶
package main import ( "context" "log" "github.com/ktr0731/apigen" "github.com/ktr0731/apigen/curl" ) func main() { def := &apigen.Definition{ Services: map[string][]*apigen.Method{ "Dummy": { { Name: "CreatePost", Request: curl.ParseCommand(`curl 'https://jsonplaceholder.typicode.com/posts' --data-binary '{"title":"foo","body":"bar","userId":1}'`), }, { Name: "GetPost", Request: curl.ParseCommand(`curl https://jsonplaceholder.typicode.com/posts?id=1`), }, { Name: "ListComments", Request: curl.ParseCommand(`curl https://jsonplaceholder.typicode.com/posts/1/comments`), ParamHint: "/posts/{postID}/comments", }, { Name: "UpdatePost", Request: curl.ParseCommand(`curl 'https://jsonplaceholder.typicode.com/posts/1' -X 'PUT' --data-binary '{"title":"foo","body":"bar","userId":1}'`), ParamHint: "/posts/{postID}", }, }, }, } if err := apigen.Generate(context.Background(), def); err != nil { log.Fatal(err) } }
Output: // Code generated by apigen; DO NOT EDIT. // github.com/ktr0731/apigen package main import ( "context" "fmt" "net/url" "github.com/ktr0731/apigen/client" ) type DummyClient interface { CreatePost(ctx context.Context, req *CreatePostRequest) (*CreatePostResponse, error) GetPost(ctx context.Context, req *GetPostRequest) (*GetPostResponse, error) ListComments(ctx context.Context, req *ListCommentsRequest) (*ListCommentsResponse, error) UpdatePost(ctx context.Context, req *UpdatePostRequest) (*UpdatePostResponse, error) } type dummyClient struct { *client.Client } func NewDummyClient(opts ...client.Option) DummyClient { return &dummyClient{Client: client.New(opts...)} } func (c *dummyClient) CreatePost(ctx context.Context, req *CreatePostRequest) (*CreatePostResponse, error) { u, err := url.Parse("https://jsonplaceholder.typicode.com/posts") if err != nil { return nil, err } var res CreatePostResponse err = c.Do(ctx, "POST", u, req.Body, &res) return &res, err } func (c *dummyClient) GetPost(ctx context.Context, req *GetPostRequest) (*GetPostResponse, error) { query := url.Values{ "id": []string{req.ID}, }.Encode() u, err := url.Parse("https://jsonplaceholder.typicode.com/posts") if err != nil { return nil, err } u.RawQuery = query var res GetPostResponse err = c.Do(ctx, "GET", u, nil, &res) return &res, err } func (c *dummyClient) ListComments(ctx context.Context, req *ListCommentsRequest) (*ListCommentsResponse, error) { u, err := url.Parse(fmt.Sprintf("https://jsonplaceholder.typicode.com/posts/%s/comments", req.PostID)) if err != nil { return nil, err } var res ListCommentsResponse err = c.Do(ctx, "GET", u, nil, &res) return &res, err } func (c *dummyClient) UpdatePost(ctx context.Context, req *UpdatePostRequest) (*UpdatePostResponse, error) { u, err := url.Parse(fmt.Sprintf("https://jsonplaceholder.typicode.com/posts/%s", req.PostID)) if err != nil { return nil, err } var res UpdatePostResponse err = c.Do(ctx, "PUT", u, req.Body, &res) return &res, err } type CreatePostRequest struct { Body *CreatePostRequestBody } type CreatePostRequestBody struct { Body string `json:"body,omitempty"` Title string `json:"title,omitempty"` UserID float64 `json:"userId,omitempty"` } type CreatePostResponse struct { ID float64 `json:"id,omitempty"` } type GetPostRequest struct { ID string } type GetPostResponse []struct { Body string `json:"body,omitempty"` ID float64 `json:"id,omitempty"` Title string `json:"title,omitempty"` UserID float64 `json:"userId,omitempty"` } type ListCommentsRequest struct { PostID string } type ListCommentsResponse []struct { Body string `json:"body,omitempty"` Email string `json:"email,omitempty"` ID float64 `json:"id,omitempty"` Name string `json:"name,omitempty"` PostID float64 `json:"postId,omitempty"` } type UpdatePostRequest struct { PostID string Body *UpdatePostRequestBody } type UpdatePostRequestBody struct { Body string `json:"body,omitempty"` Title string `json:"title,omitempty"` UserID float64 `json:"userId,omitempty"` } type UpdatePostResponse struct { ID float64 `json:"id,omitempty"` }
Types ¶
type Definition ¶
type Definition struct { // Services defines API services and its methods. // Each method name must be unique. Services map[string][]*Method }
Definition defines API metadata for code generation.
type Method ¶
type Method struct { // Name defines the name of method which represents an API. Name string // Request instantiates a new *http.Request. See examples for details. Request RequestFunc // ParamHint specifies path parameters. // These will be organized as the request fields. Each parameter must be start with ":". // For example, "/posts/:postID" is given as a ParamHint, apigen generates the following request type: // // type Request struct { // PostID string // } // // If ParamHint differs the actual path, it will be ignored and never generate any request fields. ParamHint string }
Method defines an API method.
type Option ¶
type Option func(*runner)
Option represents an option for Generate.
func WithHTTPClient ¶
WithHTTPClient specifies the HTTP client for invoking HTTP requests to know API structure. Default is *http.DefaultClient.
func WithPackage ¶
WithPackage specifies the generated file's package name. Default is main.
func WithWriter ¶
WithWriter specifies the destination writer for generated files. Default is stdout.