diff --git a/README.md b/README.md index 9e27dd601..3ca3e2b3e 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,16 @@ Check out [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) for addit ## How do I use this? `Note: The instructions below will generate the twilio-go library. These instructions can also be used interchangeably to generate other language libraries.` +### Download openapi-generator-cli.jar + +First download openapi-generator-cli.jar following the directions from the [openapi-generator GitHub repo](https://github.com/OpenAPITools/openapi-generator?tab=readme-ov-file#13---download-jar). As the openapi-generator instructions imply, ensure you have Java SDK 11 installed. OpenJDK 11 is a good way to meet the Java SDK 11 requirement. Also ensure the `JAVA_HOME` environment variable is set to the location that the SDK is installed and then add `{$JAVA_HOME}/bin` to your `PATH` environment variable. This might look like: +```sh +export JAVA_HOME=`/usr/libexec/java_home -v 1.11` +export PATH=${JAVA_HOME}/bin:$PATH +``` + +### Clone this repo + Clone this repo into your local machine. It will include: ``` @@ -33,13 +43,10 @@ Clone this repo into your local machine. It will include: |------- org.openapitools.codegen.CodegenConfig ``` -You _will_ need to make changes in at least the following: +Depending on what you are working on, files you may need to change include: -`TwilioGoGenerator.java` - -Templates in this folder: - -`src/main/resources/twilio-go` +- Templates in `src/main/resources/twilio-go` +- The code responsible for passing data to the templates: `src/main/java/com/twilio/oai/TwilioGoGenerator.java` Once modified, you can run this: @@ -51,12 +58,15 @@ In your generator project. A single jar file will be produced in `target`. You c ### For mac/linux: ``` -java -cp /path/to/openapi-generator-cli.jar:/path/to/your.jar org.openapitools.codegen.OpenAPIGenerator generate -g twilio-go -i /path/to/openapi.yaml -o ./test +java -cp /path/to/openapi-generator-cli.jar:target/twilio-openapi-generator.jar org.openapitools.codegen.OpenAPIGenerator generate -g twilio-go -i /path/to/openapi.yaml -o ./test ``` -(Do not forget to replace the values `/path/to/openapi-generator-cli.jar`, `/path/to/your.jar` and `/path/to/openapi.yaml` in the previous command) +(Do not forget to replace the values `/path/to/openapi-generator-cli.jar` and `/path/to/openapi.yaml`—to something like `twilio-oai/spec/yaml/twilio_taskrouter_v1.yaml`—in the previous command) -Here is an example script to generate [twilio-go](https://github.com/twilio/twilio-go) from our [OpenAPI specification](https://github.com/twilio/twilio-oai): [build_twilio_go.py](./examples/build_twilio_go.py). +Here is an example script to generate all of the REST API in [twilio-go](https://github.com/twilio/twilio-go) from our [OpenAPI specification](https://github.com/twilio/twilio-oai) using [build_twilio_library.py](./scripts/build_twilio_library.py): +```shell +(mvn package && python3 scripts/build_twilio_library.py -l go ../twilio-oai/spec/yaml ../twilio-go && python3 scripts/build_twilio_library.py -l go ../twilio-oai/spec/json ../twilio-go && cd ../twilio-go && goimports -w -v . && go test ./...) +``` ### For Windows You will need to use `;` instead of `:` in the classpath, e.g. @@ -109,8 +119,8 @@ To generate [`twilio-go`](https://github.com/twilio/twilio-go) from [`twilio-oai Update `` and execute the following from the root of this repo: -* To generate the entire suite, run `make install && python3 examples/build_twilio_go.py /twilio-oai/spec/yaml /twilio-go` -* To generate the provider for a single domain such as studio, run `make install && python3 examples/build_twilio_go.py /twilio-oai/spec/yaml/twilio_studio_v2.yaml /twilio-go` +* To generate the entire suite, run `make install && python3 scripts/build_twilio_library.py -l go /twilio-oai/spec/yaml /twilio-go` +* To generate the provider for a single domain such as studio, run `make install && python3 scripts/build_twilio_library.py -l go /twilio-oai/spec/yaml/twilio_studio_v2.yaml /twilio-go` ## Generating terraform-provider-twilio diff --git a/src/main/resources/twilio-go/api.mustache b/src/main/resources/twilio-go/api.mustache index b2af4e03d..86dc97ba9 100644 --- a/src/main/resources/twilio-go/api.mustache +++ b/src/main/resources/twilio-go/api.mustache @@ -3,6 +3,7 @@ package {{packageName}} {{#operations}} import ( + "context" "encoding/json" "fmt" "net/url" @@ -37,6 +38,10 @@ func (params *{{{nickname}}}Params) Set{{paramName}}({{paramName}} {{{dataType}} // {{{notes}}} {{/notes}} func (c *ApiService) {{{nickname}}}({{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}params *{{{nickname}}}Params{{/hasOptionalParams}}) ({{#returnType}}*{{{returnType}}}, {{/returnType}}error) { + return c.{{{nickname}}}WithContext(context.Background(), {{#allParams}}{{#required}}{{paramName}} {{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}params {{/hasOptionalParams}}) +} + +func (c *ApiService) {{{nickname}}}WithContext(ctx context.Context, {{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}params *{{{nickname}}}Params{{/hasOptionalParams}}) ({{#returnType}}*{{{returnType}}}, {{/returnType}}error) { path := "{{{path}}}" {{>partial_serialization}} @@ -48,10 +53,10 @@ func (c *ApiService) {{{nickname}}}({{#allParams}}{{#required}}{{paramName}} {{{ {{/headerParams}} {{/hasHeaderParams}} {{#vendorExtensions.x-is-json-type}} - resp, err := c.requestHandler.{{httpMethod}}(c.baseURL+path, data, headers, body...) + resp, err := c.requestHandler.{{httpMethod}}WithContext(ctx, c.baseURL+path, data, headers, body...) {{/vendorExtensions.x-is-json-type}} {{^vendorExtensions.x-is-json-type}} - resp, err := c.requestHandler.{{httpMethod}}(c.baseURL+path, data, headers) + resp, err := c.requestHandler.{{httpMethod}}WithContext(ctx, c.baseURL+path, data, headers) {{/vendorExtensions.x-is-json-type}} {{#returnType}} if err != nil { @@ -81,6 +86,11 @@ func (c *ApiService) {{{nickname}}}({{#allParams}}{{#required}}{{paramName}} {{{ {{#vendorExtensions.x-is-read-operation}} // Retrieve a single page of {{{vendorExtensions.x-domain-name}}} records from the API. Request is executed immediately. func (c *ApiService) Page{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params *{{{nickname}}}Params, pageToken, pageNumber string) (*{{{returnContainer}}}, error) { + return c.Page{{{vendorExtensions.x-domain-name}}}WithContext(context.Background(), {{#allParams}}{{#required}}{{paramName}} {{^last}}, {{/last}}{{/required}}{{/allParams}}params, pageToken, pageNumber) +} + +// Retrieve a single page of {{{vendorExtensions.x-domain-name}}} records from the API. Request is executed immediately. +func (c *ApiService) Page{{{vendorExtensions.x-domain-name}}}WithContext(ctx context.Context, {{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params *{{{nickname}}}Params, pageToken, pageNumber string) (*{{{returnContainer}}}, error) { path := "{{{path}}}" {{>partial_serialization}} @@ -91,7 +101,7 @@ func (c *ApiService) Page{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{#r data.Set("Page", pageNumber) } - resp, err := c.requestHandler.Get(c.baseURL+path, data, headers) + resp, err := c.requestHandler.GetWithContext(ctx, c.baseURL+path, data, headers) if err != nil { return nil, err } @@ -108,7 +118,12 @@ func (c *ApiService) Page{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{#r // Lists {{{vendorExtensions.x-domain-name}}} records from the API as a list. Unlike stream, this operation is eager and loads 'limit' records into memory before returning. func (c *ApiService) List{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params *{{{nickname}}}Params) ({{{returnType}}}, error) { - response, errors := c.Stream{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{#required}}{{paramName}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params) + return c.List{{{vendorExtensions.x-domain-name}}}WithContext(context.Background(), {{#allParams}}{{#required}}{{paramName}} {{^last}}, {{/last}}{{/required}}{{/allParams}}params) +} + +// Lists {{{vendorExtensions.x-domain-name}}} records from the API as a list. Unlike stream, this operation is eager and loads 'limit' records into memory before returning. +func (c *ApiService) List{{{vendorExtensions.x-domain-name}}}WithContext(ctx context.Context, {{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params *{{{nickname}}}Params) ({{{returnType}}}, error) { + response, errors := c.Stream{{{vendorExtensions.x-domain-name}}}WithContext(ctx, {{#allParams}}{{#required}}{{paramName}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params) records := make({{{returnType}}}, 0) for record := range response { @@ -124,6 +139,11 @@ func (c *ApiService) List{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{#r // Streams {{{vendorExtensions.x-domain-name}}} records from the API as a channel stream. This operation lazily loads records as efficiently as possible until the limit is reached. func (c *ApiService) Stream{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params *{{{nickname}}}Params) (chan {{{returnBaseType}}}, chan error) { + return c.Stream{{{vendorExtensions.x-domain-name}}}WithContext(context.Background(), {{#allParams}}{{#required}}{{paramName}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params) +} + +// Streams {{{vendorExtensions.x-domain-name}}} records from the API as a channel stream. This operation lazily loads records as efficiently as possible until the limit is reached. +func (c *ApiService) Stream{{{vendorExtensions.x-domain-name}}}WithContext(ctx context.Context, {{#allParams}}{{#required}}{{paramName}} {{{dataType}}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params *{{{nickname}}}Params) (chan {{{returnBaseType}}}, chan error) { if params == nil { params = &{{{nickname}}}Params{} } @@ -132,20 +152,20 @@ func (c *ApiService) Stream{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{ recordChannel := make(chan {{{returnBaseType}}}, 1) errorChannel := make(chan error, 1) - response, err := c.Page{{{vendorExtensions.x-domain-name}}}({{#allParams}}{{#required}}{{paramName}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params, "", "") + response, err := c.Page{{{vendorExtensions.x-domain-name}}}WithContext(ctx, {{#allParams}}{{#required}}{{paramName}}{{^last}}, {{/last}}{{/required}}{{/allParams}}params, "", "") if err != nil { errorChannel <- err close(recordChannel) close(errorChannel) } else { - go c.stream{{{vendorExtensions.x-domain-name}}}(response, params, recordChannel, errorChannel) + go c.stream{{{vendorExtensions.x-domain-name}}}WithContext(ctx, response, params, recordChannel, errorChannel) } return recordChannel, errorChannel } -func (c *ApiService) stream{{{vendorExtensions.x-domain-name}}}(response *{{{returnContainer}}}, params *{{{nickname}}}Params, recordChannel chan {{{returnBaseType}}}, errorChannel chan error) { +func (c *ApiService) stream{{{vendorExtensions.x-domain-name}}}WithContext(ctx context.Context, response *{{{returnContainer}}}, params *{{{nickname}}}Params, recordChannel chan {{{returnBaseType}}}, errorChannel chan error) { curRecord := 1 for response != nil { @@ -160,7 +180,7 @@ func (c *ApiService) stream{{{vendorExtensions.x-domain-name}}}(response *{{{ret } } - record, err := client.GetNext(c.baseURL, response, c.getNext{{{returnContainer}}}) + record, err := client.GetNextWithContext(ctx, c.baseURL, response, c.getNext{{{returnContainer}}}WithContext) if err != nil { errorChannel <- err break @@ -175,11 +195,11 @@ func (c *ApiService) stream{{{vendorExtensions.x-domain-name}}}(response *{{{ret close(errorChannel) } -func (c *ApiService) getNext{{{returnContainer}}}(nextPageUrl string) (interface{}, error) { +func (c *ApiService) getNext{{{returnContainer}}}WithContext(ctx context.Context, nextPageUrl string) (interface{}, error) { if nextPageUrl == "" { return nil, nil } - resp, err := c.requestHandler.Get(nextPageUrl, nil, nil) + resp, err := c.requestHandler.GetWithContext(ctx, nextPageUrl, nil, nil) if err != nil { return nil, err }