Skip to content

[Dart 2] Add support for Dart 2 #754

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from Aug 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cache:
- $HOME/perl5
- $HOME/.cargo
- $HOME/.stack
- $HOME/.pub-cache
- $HOME/samples/server/petstore/cpp-pistache/pistache

services:
Expand Down Expand Up @@ -70,6 +71,13 @@ before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq bats
- sudo apt-get install -qq curl
# install dart
#- sudo apt-get update
- sudo apt-get install apt-transport-https
- sudo sh -c 'curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
- sudo sh -c 'curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
- sudo apt-get update
- sudo apt-get install dart
# install perl module
#- cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
#- cpanm Test::Exception Test::More Log::Any LWP::UserAgent JSON URI:Query Module::Runtime DateTime Module::Find Moose::Role
Expand All @@ -94,11 +102,13 @@ install:
# Add Godeps dependencies to GOPATH and PATH
#- eval "$(curl -sL https://raw.githubusercontent.com/travis-ci/gimme/master/gimme | GIMME_GO_VERSION=1.4 bash)"
#- export GOPATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace"
- export PATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace/bin:$HOME/.cargo/bin:$PATH"
- export PATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace/bin:$HOME/.cargo/bin:$PATH:/usr/lib/dart/bin"
#- go version
- gcc -v
- echo $CC
- echo $CXX
- pub version
- dart --version

script:
# fail fast
Expand Down
50 changes: 50 additions & 0 deletions bin/dart2-petstore.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/sh

SCRIPT="$0"
echo "# START SCRIPT: $SCRIPT"

while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done

if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi

executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"

if [ ! -f "$executable" ]
then
mvn -B clean package
fi

# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"

# Generate non-browserClient
ags="generate -t modules/openapi-generator/src/main/resources/dart -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g dart -o samples/client/petstore/dart2/openapi -DhideGenerationTimestamp=true -DbrowserClient=false --additional-properties supportDart2=true $@"

# then options to generate the library for vm would be:
#ags="generate -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g dart -o samples/client/petstore/dart2/openapi_vm -DbrowserClient=false -DpubName=openapi_vm $@"
java $JAVA_OPTS -jar $executable $ags

# Generate browserClient
ags="generate -t modules/openapi-generator/src/main/resources/dart -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g dart -o samples/client/petstore/dart2/openapi-browser-client -DhideGenerationTimestamp=true -DbrowserClient=true --additional-properties supportDart2=true $@"
java $JAVA_OPTS -jar $executable $ags

# Generate non-browserClient and put it to the flutter sample app
ags="generate -t modules/openapi-generator/src/main/resources/dart -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g dart -o samples/client/petstore/dart2/flutter_petstore/openapi -DhideGenerationTimestamp=true -DbrowserClient=false --additional-properties supportDart2=true $@"
java $JAVA_OPTS -jar $executable $ags

# There is a proposal to allow importing different libraries depending on the environment:
# https://github.com/munificent/dep-interface-libraries
# When this is implemented there will only be one library.

# The current petstore test will then work for both: the browser library and the vm library.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.openapitools.codegen.utils.ModelUtils;

import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.parser.util.SchemaTypeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -47,6 +48,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String PUB_VERSION = "pubVersion";
public static final String PUB_DESCRIPTION = "pubDescription";
public static final String USE_ENUM_EXTENSION = "useEnumExtension";
public static final String SUPPORT_DART2 = "supportDart2";
protected boolean browserClient = true;
protected String pubName = "openapi";
protected String pubVersion = "1.0.0";
Expand Down Expand Up @@ -124,6 +126,7 @@ public DartClientCodegen() {
cliOptions.add(new CliOption(PUB_DESCRIPTION, "Description in generated pubspec"));
cliOptions.add(new CliOption(USE_ENUM_EXTENSION, "Allow the 'x-enum-values' extension for enums"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated code"));
cliOptions.add(CliOption.newBoolean(SUPPORT_DART2, "support dart2").defaultValue(Boolean.FALSE.toString()));
}

@Override
Expand Down Expand Up @@ -188,9 +191,14 @@ public void processOpts() {
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);

final Object isSupportDart2 = additionalProperties.get(SUPPORT_DART2);
if (Boolean.TRUE.equals(isSupportDart2) || (isSupportDart2 instanceof String && Boolean.parseBoolean((String)isSupportDart2))) {
embeddedTemplateDir = templateDir = "dart2";
} else {
supportingFiles.add(new SupportingFile("analysis_options.mustache", "", ".analysis_options"));
}
final String libFolder = sourceFolder + File.separator + "lib";
supportingFiles.add(new SupportingFile("pubspec.mustache", "", "pubspec.yaml"));
supportingFiles.add(new SupportingFile("analysis_options.mustache", "", ".analysis_options"));
supportingFiles.add(new SupportingFile("api_client.mustache", libFolder, "api_client.dart"));
supportingFiles.add(new SupportingFile("api_exception.mustache", libFolder, "api_exception.dart"));
supportingFiles.add(new SupportingFile("api_helper.mustache", libFolder, "api_helper.dart"));
Expand Down
133 changes: 133 additions & 0 deletions modules/openapi-generator/src/main/resources/dart2/README.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# {{pubName}}
{{#appDescription}}
{{{appDescription}}}
{{/appDescription}}

This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:

- API version: {{appVersion}}
{{#artifactVersion}}
- Package version: {{artifactVersion}}
{{/artifactVersion}}
{{^hideGenerationTimestamp}}
- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}
- Build package: {{generatorClass}}
{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}

## Requirements

Dart 1.20.0 or later OR Flutter 0.0.20 or later

## Installation & Usage

### Github
If this Dart package is published to Github, please include the following in pubspec.yaml
```
name: {{pubName}}
version: {{pubVersion}}
description: {{pubDescription}}
dependencies:
{{pubName}}:
git: https://github.com/{{gitUserId}}/{{gitRepoId}}.git
version: 'any'
```

### Local
To use the package in your local drive, please include the following in pubspec.yaml
```
dependencies:
{{pubName}}:
path: /path/to/{{pubName}}
```

## Tests

TODO

## Getting Started

Please follow the [installation procedure](#installation--usage) and then run the following:

```dart
import 'package:{{pubName}}/api.dart';
{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}
{{#hasAuthMethods}}
{{#authMethods}}
{{#isBasic}}
// TODO Configure HTTP basic authorization: {{{name}}}
//{{pubName}}.api.Configuration.username = 'YOUR_USERNAME';
//{{pubName}}.api.Configuration.password = 'YOUR_PASSWORD';
{{/isBasic}}
{{#isApiKey}}
// TODO Configure API key authorization: {{{name}}}
//{{pubName}}.api.Configuration.apiKey{'{{{keyParamName}}}'} = 'YOUR_API_KEY';
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
//{{pubName}}.api.Configuration.apiKeyPrefix{'{{{keyParamName}}}'} = "Bearer";
{{/isApiKey}}
{{#isOAuth}}
// TODO Configure OAuth2 access token for authorization: {{{name}}}
//{{pubName}}.api.Configuration.accessToken = 'YOUR_ACCESS_TOKEN';
{{/isOAuth}}
{{/authMethods}}
{{/hasAuthMethods}}

var api_instance = new {{classname}}();
{{#allParams}}
var {{paramName}} = {{#isListContainer}}[{{/isListContainer}}{{#isBodyParam}}new {{dataType}}(){{/isBodyParam}}{{^isBodyParam}}{{{example}}}{{/isBodyParam}}{{#isListContainer}}]{{/isListContainer}}; // {{{dataType}}} | {{{description}}}
{{/allParams}}

try {
{{#returnType}}var result = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{#returnType}}
print(result);
{{/returnType}}
} catch (e) {
print("Exception when calling {{classname}}->{{operationId}}: $e\n");
}
{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}}
```

## Documentation for API Endpoints

All URIs are relative to *{{basePath}}*

Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}/{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}

## Documentation For Models

{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}/{{{classname}}}.md)
{{/model}}{{/models}}

## Documentation For Authorization

{{^authMethods}} All endpoints do not require authorization.
{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}}
{{#authMethods}}## {{{name}}}

{{#isApiKey}}- **Type**: API key
- **API key parameter name**: {{{keyParamName}}}
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
{{/isApiKey}}
{{#isBasic}}- **Type**: HTTP basic authentication
{{/isBasic}}
{{#isOAuth}}- **Type**: OAuth
- **Flow**: {{{flow}}}
- **Authorization URL**: {{{authorizationUrl}}}
- **Scopes**: {{^scopes}}N/A{{/scopes}}
{{#scopes}} - **{{{scope}}}**: {{{description}}}
{{/scopes}}
{{/isOAuth}}

{{/authMethods}}

## Author

{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}}
{{/hasMore}}{{/apis}}{{/apiInfo}}

117 changes: 117 additions & 0 deletions modules/openapi-generator/src/main/resources/dart2/api.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
part of {{pubName}}.api;

{{#operations}}


class {{classname}} {
final ApiClient apiClient;

{{classname}}([ApiClient apiClient]) : apiClient = apiClient ?? defaultApiClient;

{{#operation}}
/// {{summary}}
///
/// {{notes}}
{{#returnType}}Future<{{{returnType}}}> {{/returnType}}{{^returnType}}Future {{/returnType}}{{nickname}}({{#allParams}}{{#required}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async {
Object postBody{{#bodyParam}} = {{paramName}}{{/bodyParam}};

// verify required params are set
{{#allParams}}
{{#required}}
if({{paramName}} == null) {
throw new ApiException(400, "Missing required param: {{paramName}}");
}
{{/required}}
{{/allParams}}

// create path and map variables
String path = "{{{path}}}".replaceAll("{format}","json"){{#pathParams}}.replaceAll("{" + "{{baseName}}" + "}", {{{paramName}}}.toString()){{/pathParams}};

// query params
List<QueryParam> queryParams = [];
Map<String, String> headerParams = {};
Map<String, String> formParams = {};
{{#queryParams}}
{{^required}}
if({{paramName}} != null) {
{{/required}}
queryParams.addAll(_convertParametersForCollectionFormat("{{collectionFormat}}", "{{baseName}}", {{paramName}}));
{{^required}}
}
{{/required}}
{{/queryParams}}
{{#headerParams}}
headerParams["{{baseName}}"] = {{paramName}};
{{/headerParams}}

List<String> contentTypes = [{{#consumes}}"{{{mediaType}}}"{{#hasMore}},{{/hasMore}}{{/consumes}}];

String contentType = contentTypes.length > 0 ? contentTypes[0] : "application/json";
List<String> authNames = [{{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}];

if(contentType.startsWith("multipart/form-data")) {
bool hasFields = false;
MultipartRequest mp = new MultipartRequest(null, null);
{{#formParams}}
{{^isFile}}
if ({{paramName}} != null) {
hasFields = true;
mp.fields['{{baseName}}'] = parameterToString({{paramName}});
}
{{/isFile}}
{{#isFile}}
if ({{paramName}} != null) {
hasFields = true;
mp.fields['{{baseName}}'] = {{paramName}}.field;
mp.files.add({{paramName}});
}
{{/isFile}}
{{/formParams}}
if(hasFields)
postBody = mp;
}
else {
{{#formParams}}
{{^isFile}}
if ({{paramName}} != null)
formParams['{{baseName}}'] = parameterToString({{paramName}});
{{/isFile}}
{{/formParams}}
}

var response = await apiClient.invokeAPI(path,
'{{httpMethod}}',
queryParams,
postBody,
headerParams,
formParams,
contentType,
authNames);

if(response.statusCode >= 400) {
throw new ApiException(response.statusCode, response.body);
} else if(response.body != null) {
{{#isListContainer}}
{{#returnType}}
return (apiClient.deserialize(response.body, '{{{returnType}}}') as List).map((item) => item as {{returnBaseType}}).toList();
{{/returnType}}
{{/isListContainer}}
{{^isListContainer}}
{{#isMapContainer}}
{{#returnType}}
return new {{{returnType}}}.from(apiClient.deserialize(response.body, '{{{returnType}}}'));
{{/returnType}};
{{/isMapContainer}}
{{^isMapContainer}}
{{#returnType}}
return apiClient.deserialize(response.body, '{{{returnType}}}') as {{{returnType}}};
{{/returnType}}
{{/isMapContainer}}
{{/isListContainer}}
} else {
return{{#returnType}} null{{/returnType}};
}
}
{{/operation}}
}
{{/operations}}
Loading