forked from loafle/openapi-generator-original
Compare commits
76 Commits
ue4-docker
...
typescript
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b8e4c27c2 | ||
|
|
277e4ed49d | ||
|
|
e2aaf66917 | ||
|
|
a7ac715e80 | ||
|
|
c4cc0f705b | ||
|
|
91f4e9fb8f | ||
|
|
6bd05358db | ||
|
|
dee6ed420e | ||
|
|
41d1864d02 | ||
|
|
56f9737b2d | ||
|
|
e315d48636 | ||
|
|
659369c3ea | ||
|
|
303ec6c04b | ||
|
|
391a191ecf | ||
|
|
934f226098 | ||
|
|
07dd1efb7a | ||
|
|
5a2561f520 | ||
|
|
d704a4ffba | ||
|
|
bfc14c82e5 | ||
|
|
9afb8ff12a | ||
|
|
0000342d77 | ||
|
|
0f3ad99d72 | ||
|
|
4f461f948a | ||
|
|
68241f8c33 | ||
|
|
5fd3be29bd | ||
|
|
e4a0855db9 | ||
|
|
9297e59053 | ||
|
|
6c37c7180d | ||
|
|
fb6f8c5344 | ||
|
|
8d8e57f1f9 | ||
|
|
495ce938f8 | ||
|
|
99c3dceae7 | ||
|
|
fcbecc4dbd | ||
|
|
40f3c4f4dd | ||
|
|
c330a9f872 | ||
|
|
a481d0ce83 | ||
|
|
35d3cc20c9 | ||
|
|
7a372acbed | ||
|
|
56ca583b2e | ||
|
|
c8c58b4f5e | ||
|
|
861f774c56 | ||
|
|
df970ae8b1 | ||
|
|
1d27563a41 | ||
|
|
aeef285190 | ||
|
|
8068315f79 | ||
|
|
e11a5a9395 | ||
|
|
a00e342505 | ||
|
|
7786f2e9fb | ||
|
|
1c2943dcc8 | ||
|
|
c5c9a59060 | ||
|
|
8bfb88cd76 | ||
|
|
35b98cf2bc | ||
|
|
9b0bb9a399 | ||
|
|
e41df36261 | ||
|
|
c2b7422a81 | ||
|
|
525f48d694 | ||
|
|
0867522b0a | ||
|
|
988df1f7a5 | ||
|
|
4c11314a7b | ||
|
|
3eaa5e54ef | ||
|
|
7909cbaec7 | ||
|
|
a6560e5530 | ||
|
|
61a1bbdabe | ||
|
|
a7de49110e | ||
|
|
e40d94984f | ||
|
|
a8ec866117 | ||
|
|
f5b062957d | ||
|
|
d4fa8c7f72 | ||
|
|
6b2a2289f2 | ||
|
|
b89646a223 | ||
|
|
276d7d47e5 | ||
|
|
1cc6fb0421 | ||
|
|
1a31c48ceb | ||
|
|
6638cef37a | ||
|
|
05f64c6732 | ||
|
|
06d9556f13 |
@@ -21,6 +21,7 @@ cache:
|
||||
- $HOME/samples/client/petstore/php/OpenAPIToolsClient-php/vendor
|
||||
- $HOME/samples/client/petstore/ruby/vendor/bundle
|
||||
- $HOME/samples/client/petstore/python/.venv/
|
||||
- $HOME/samples/client/petstore/typescript/tests/default/node_modules
|
||||
- $HOME/samples/client/petstore/typescript-node/npm/node_modules
|
||||
- $HOME/samples/client/petstore/typescript-node/npm/typings/
|
||||
- $HOME/samples/client/petstore/typescript-fetch/tests/default/node_modules
|
||||
|
||||
@@ -2,11 +2,6 @@ kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
# test ue4 cpp client
|
||||
- name: cpp-ue4
|
||||
image: adamrehn/ue4-full:4.21.0
|
||||
commands:
|
||||
- (cd samples/client/petstore/cpp-ue4/ && ue4 build)
|
||||
# test aspnetcore 3.x
|
||||
- name: aspnetcore-test
|
||||
image: mcr.microsoft.com/dotnet/core/sdk:3.1
|
||||
|
||||
@@ -122,6 +122,7 @@ public class ApiClientTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore("There is no more basic auth in petstore security definitions")
|
||||
@Test
|
||||
public void testSetUsernameAndPassword() {
|
||||
HttpBasicAuth auth = null;
|
||||
|
||||
@@ -122,6 +122,7 @@ public class ApiClientTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore("There is no more basic auth in petstore security definitions")
|
||||
@Test
|
||||
public void testSetUsernameAndPassword() {
|
||||
HttpBasicAuth auth = null;
|
||||
|
||||
@@ -128,6 +128,7 @@ public class ApiClientTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore("There is no more basic auth in petstore security definitions")
|
||||
@Test
|
||||
public void testSetUsernameAndPassword() {
|
||||
HttpBasicAuth auth = null;
|
||||
|
||||
@@ -745,11 +745,9 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in
|
||||
- 2020-03-15 - [Load Testing Your API with Swagger/OpenAPI and k6](https://k6.io/blog/load-testing-your-api-with-swagger-openapi-and-k6)
|
||||
- 2020-04-13 - [俺的【OAS】との向き合い方 (爆速でOpenAPIと友達になろう)](https://tech-blog.optim.co.jp/entry/2020/04/13/100000) in [OPTim Blog](https://tech-blog.optim.co.jp/)
|
||||
- 2020-04-22 - [Introduction to OpenAPI Generator](https://nordicapis.com/introduction-to-openapi-generator/) by [Kristopher Sandoval](https://nordicapis.com/author/sandovaleffect/) in [Nordic APIs](https://nordicapis.com/)
|
||||
- 2020-04-27 - [How we use Open API v3 specification to auto-generate API documentation, code-snippets and clients](https://medium.com/pdf-generator-api/how-we-use-open-api-v3-specification-to-auto-generate-api-documentation-code-snippets-and-clients-d127a3cea784) by [Tanel Tähepõld](https://medium.com/@tanel.tahepold)
|
||||
- 2020-05-09 - [OpenAPIでお手軽にモックAPIサーバーを動かす](https://qiita.com/kasa_le/items/97ca6a8dd4605695c25c) by [Sachie Kamba](https://qiita.com/kasa_le)
|
||||
- 2020-05-18 - [Spring Boot REST with OpenAPI 3](https://dev.to/alfonzjanfrithz/spring-boot-rest-with-openapi-3-59jm) by [Alfonz Jan Frithz](https://dev.to/alfonzjanfrithz)
|
||||
- 2020-05-19 - [Dead Simple APIs with Open API](https://www.youtube.com/watch?v=sIaXmR6xRAw) by [Chris Tankersley](https://github.com/dragonmantank) at [Nexmo](https://developer.nexmo.com/)
|
||||
- 2020-05-22 - [TypeScript REST API Client](https://dev.to/unhurried/typescript-rest-api-client-4in3) by ["unhurried"](https://dev.to/unhurried)
|
||||
|
||||
## [6 - About Us](#table-of-contents)
|
||||
|
||||
@@ -779,7 +777,6 @@ Here is a list of template creators:
|
||||
* Bash: @bkryza
|
||||
* C: @PowerOfCreation @zhemant [:heart:](https://www.patreon.com/zhemant)
|
||||
* C++ REST: @Danielku15
|
||||
* C++ UE4: @Kahncode
|
||||
* C# (.NET 2.0): @who
|
||||
* C# (.NET Standard 1.3 ): @Gronsak
|
||||
* C# (.NET 4.5 refactored): @jimschubert [:heart:](https://www.patreon.com/jimschubert)
|
||||
|
||||
@@ -27,6 +27,6 @@ fi
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="generate -t modules/openapi-generator/src/main/resources/nodejs-express-server -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g nodejs-express-server -o samples/server/petstore/nodejs-express-server $@"
|
||||
ags="generate -t modules/openapi-generator/src/main/resources/nodejs-express-server -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g nodejs-express-server -o samples/server/petstore/nodejs-express-server -Dservice $@"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
|
||||
@@ -28,7 +28,7 @@ fi
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
|
||||
args="generate -t modules/openapi-generator/src/main/resources/ocaml -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g ocaml -o samples/client/petstore/ocaml --additional-properties packageName=petstore_client $@"
|
||||
args="generate -t modules/openapi-generator/src/main/resources/ocaml -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g ocaml -o samples/client/petstore/ocaml --additional-properties packageName=petstore_client $@"
|
||||
|
||||
echo "java ${JAVA_OPTS} -jar ${executable} ${args}"
|
||||
java $JAVA_OPTS -jar $executable $args
|
||||
|
||||
@@ -26,7 +26,9 @@ then
|
||||
fi
|
||||
|
||||
# if you've executed sbt assembly previously it will use that instead.
|
||||
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
|
||||
ags="generate -i modules/openapi-generator/src/test/resources/3_0/composed-schemas.yaml -g typescript-axios -o samples/client/petstore/typescript-axios/builds/composed-schemas $@"
|
||||
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DdebugOperations -DloggerPath=conf/log4j.properties"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
args="generate -t modules/openapi-generator/src/main/resources/ocaml -i modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml -g ocaml -o samples/openapi3/client/petstore/ocaml/ --additional-properties packageName=petstore_client $@"
|
||||
|
||||
echo "java ${JAVA_OPTS} -jar ${executable} ${args}"
|
||||
java $JAVA_OPTS -jar $executable $args
|
||||
@@ -37,8 +37,8 @@ ags="generate -t $resources -i $input -g $generator -o $out_folder $@"
|
||||
rm -rf $out_folder/.openapi*
|
||||
rm -rf $out_folder/openapi_server
|
||||
rm -rf $out_folder/tests*
|
||||
rm -f $out_folder/README.md
|
||||
rm -f $out_folder/requirements.txt
|
||||
rm -f $out_folder/test-requirements.txt
|
||||
rm $out_folder/README.md
|
||||
rm $out_folder/requirements.txt
|
||||
rm $out_folder/test-requirements.txt
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
|
||||
@@ -6,5 +6,4 @@
|
||||
./bin/typescript-axios-petstore-with-complex-headers.sh
|
||||
./bin/typescript-axios-petstore-with-single-request-parameters.sh
|
||||
./bin/typescript-axios-petstore-interfaces.sh
|
||||
./bin/typescript-axios-petstore-composed-schemas.sh
|
||||
./bin/typescript-axios-petstore.sh
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT="$0"
|
||||
echo "# START SCRIPT: $SCRIPT"
|
||||
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=`ls -ld "$SCRIPT"`
|
||||
@@ -21,11 +22,16 @@ executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
|
||||
|
||||
if [ ! -f "$executable" ]
|
||||
then
|
||||
mvn clean package
|
||||
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"
|
||||
ags="$@ generate -t modules/openapi-generator/src/main/resources/cpp-ue4 -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g cpp-ue4 -o samples/client/petstore/cpp-ue4"
|
||||
echo "Creating default (fetch) client!"
|
||||
ags="generate -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g typescript -o samples/openapi3/client/petstore/typescript/builds/default --additional-properties=platform=node,npmName=ts-petstore-client $@"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
echo "Creating jquery client!"
|
||||
ags="generate -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g typescript -o samples/openapi3/client/petstore/typescript/builds/jquery --additional-properties=framework=jquery,npmName=ts-petstore-client $@"
|
||||
|
||||
java $JAVA_OPTS -jar $executable $ags
|
||||
@@ -50,6 +50,7 @@ declare -a samples=(
|
||||
#"${root}/bin/php-slim4-server-petstore.sh"
|
||||
"${root}/bin/php-ze-ph-petstore-server.sh"
|
||||
"${root}/bin/openapi3/php-petstore.sh"
|
||||
"${root}/bin/typescript.sh"
|
||||
"${root}/bin/typescript-angularjs-petstore.sh"
|
||||
"${root}/bin/typescript-angular-petstore-all.sh"
|
||||
"${root}/bin/typescript-aurelia-petstore.sh"
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
|
||||
|
||||
If Not Exist %executable% (
|
||||
mvn clean package
|
||||
)
|
||||
|
||||
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
|
||||
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g cpp-ue4 -o samples\client\petstore\cpp-ue4
|
||||
|
||||
java %JAVA_OPTS% -jar %executable% %ags%
|
||||
@@ -1,24 +1,24 @@
|
||||
call .\bin\windows\java-petstore-feign-10x.bat
|
||||
call .\bin\windows\java-petstore-feign.bat
|
||||
call .\bin\windows\java-petstore-google-api-client.bat
|
||||
call .\bin\windows\java-petstore-jersey1.bat
|
||||
call .\bin\windows\java-petstore-jersey2-java6.bat
|
||||
call .\bin\windows\java-petstore-jersey2-java7.bat
|
||||
call .\bin\windows\java-petstore-jersey2-java8.bat
|
||||
call .\bin\windows\java-petstore-feign.bat
|
||||
call .\bin\windows\java-petstore-feign-10x.bat
|
||||
call .\bin\windows\java-petstore-native.bat
|
||||
call .\bin\windows\java-petstore-okhttp-gson-parcelable.bat
|
||||
call .\bin\windows\java-petstore-okhttp-gson.bat
|
||||
call .\bin\windows\java-petstore-rest-assured.bat
|
||||
call .\bin\windows\java-petstore-rest-assured-jackson.bat
|
||||
call .\bin\windows\java-petstore-resteasy.bat
|
||||
call .\bin\windows\java-petstore-resttemplate-withxml.bat
|
||||
call .\bin\windows\java-petstore-resttemplate.bat
|
||||
call .\bin\windows\java-petstore-okhttp-gson-parcelable.bat
|
||||
call .\bin\windows\java-petstore-retrofit.bat
|
||||
call .\bin\windows\java-petstore-retrofit2-play24.bat
|
||||
call .\bin\windows\java-petstore-retrofit2-play25.bat
|
||||
call .\bin\windows\java-petstore-retrofit2-play26.bat
|
||||
call .\bin\windows\java-petstore-retrofit2.bat
|
||||
call .\bin\windows\java-petstore-retrofit2rx.bat
|
||||
call .\bin\windows\java-petstore-retrofit2rx2.bat
|
||||
call .\bin\windows\java-petstore-vertx.bat
|
||||
call .\bin\windows\java8-petstore-jersey2.bat
|
||||
call .\bin\windows\java-petstore-retrofit2-play24.bat
|
||||
call .\bin\windows\java-petstore-retrofit2-play25.bat
|
||||
call .\bin\windows\java-petstore-retrofit2-play26.bat
|
||||
call .\bin\windows\java-petstore-jersey2-java6.bat
|
||||
call .\bin\windows\java-petstore-resttemplate.bat
|
||||
call .\bin\windows\java-petstore-resttemplate-withxml.bat
|
||||
call .\bin\windows\java-petstore-webclient.bat
|
||||
call .\bin\windows\java-petstore-resteasy.bat
|
||||
call .\bin\windows\java-petstore-google-api-client.bat
|
||||
call .\bin\windows\java-petstore-rest-assured.bat
|
||||
call .\bin\windows\java-petstore-rest-assured-jackson.bat
|
||||
call .\bin\windows\java-petstore-vertx.bat
|
||||
|
||||
@@ -5,6 +5,6 @@ If Not Exist %executable% (
|
||||
)
|
||||
|
||||
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
|
||||
set ags=generate --artifact-id petstore-java-client-jersey1 -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -o samples\client\petstore\java\jersey1 --additional-properties hideGenerationTimestamp=true --library=jersey1
|
||||
set ags=generate --artifact-id petstore-java-client-jersey1 -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -o samples\client\petstore\java\jersey1 --additional-properties hideGenerationTimestamp=true --library=jersey1 --additional-properties useNullForUnknownEnumValue=true
|
||||
|
||||
java %JAVA_OPTS% -jar %executable% %ags%
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
|
||||
|
||||
If Not Exist %executable% (
|
||||
mvn clean package
|
||||
)
|
||||
|
||||
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
|
||||
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-jersey2-java7.json -o samples\client\petstore\java\jersey2-java7 --additional-properties hideGenerationTimestamp=true
|
||||
|
||||
java %JAVA_OPTS% -jar %executable% %ags%
|
||||
@@ -5,6 +5,6 @@ If Not Exist %executable% (
|
||||
)
|
||||
|
||||
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
|
||||
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-jersey2-java8.json -o samples\client\petstore\java\jersey2-java8 --additional-properties hideGenerationTimestamp=true
|
||||
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-jersey2-java7.json -o samples\client\petstore\java\jersey2 --additional-properties hideGenerationTimestamp=true
|
||||
|
||||
java %JAVA_OPTS% -jar %executable% %ags%
|
||||
|
||||
@@ -5,6 +5,6 @@ If Not Exist %executable% (
|
||||
)
|
||||
|
||||
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
|
||||
set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\rest-assured -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-rest-assured.json -o samples\client\petstore\java\rest-assured --additional-properties hideGenerationTimestamp=true --additional-properties useBeanValidation=true --additional-properties performBeanValidation=true --additional-properties booleanGetterPrefix=is
|
||||
set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\rest-assured -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-rest-assured.json -o samples\client\petstore\java\rest-assured --additional-properties hideGenerationTimestamp=true,booleanGetterPrefix=is
|
||||
|
||||
java %JAVA_OPTS% -jar %executable% %ags%
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
|
||||
|
||||
If Not Exist %executable% (
|
||||
mvn clean package
|
||||
)
|
||||
|
||||
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
|
||||
set ags=generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-webclient.json -o samples/client/petstore/java/webclient --additional-properties hideGenerationTimestamp=true
|
||||
|
||||
java %JAVA_OPTS% -jar %executable% %ags%
|
||||
@@ -5,6 +5,6 @@ If Not Exist %executable% (
|
||||
)
|
||||
|
||||
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties
|
||||
set ags=generate -i modules\openapi-generator\src\test\resources\3_0\petstore.yaml -g ocaml -o samples\client\petstore\ocaml
|
||||
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g ocaml -o samples\client\petstore\ocaml
|
||||
|
||||
java %JAVA_OPTS% -jar %executable% %ags%
|
||||
|
||||
@@ -6,5 +6,4 @@ call bin\windows\typescript-axios-petstore-with-complex-headers.bat
|
||||
call bin\windows\typescript-axios-petstore-with-single-request-parameters.bat
|
||||
call bin\windows\typescript-axios-petstore-with-npm-version.bat
|
||||
call bin\windows\typescript-axios-petstore-interfaces.bat
|
||||
call bin\windows\typescript-axios-petstore-composed-schemas.bat
|
||||
call bin\windows\typescript-axios-petstore-with-npm-version-and-separate-models-and-api.bat
|
||||
@@ -1,14 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
|
||||
|
||||
If Not Exist %executable% (
|
||||
mvn clean package
|
||||
)
|
||||
|
||||
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
|
||||
|
||||
echo
|
||||
set ags=generate -i modules\openapi-generator\src\test\resources\3_0\composed-schemas.yaml -g typescript-axios -o samples\client\petstore\typescript-axios\builds\composed-schemas
|
||||
|
||||
java %JAVA_OPTS% -jar %executable% %ags%
|
||||
@@ -15,7 +15,6 @@ The following generators are available:
|
||||
* [cpp-qt5-client](generators/cpp-qt5-client.md)
|
||||
* [cpp-restsdk](generators/cpp-restsdk.md)
|
||||
* [cpp-tizen](generators/cpp-tizen.md)
|
||||
* [cpp-ue4 (beta)](generators/cpp-ue4.md)
|
||||
* [csharp](generators/csharp.md)
|
||||
* [csharp-dotnet2 (deprecated)](generators/csharp-dotnet2.md)
|
||||
* [csharp-netcore](generators/csharp-netcore.md)
|
||||
@@ -60,6 +59,7 @@ The following generators are available:
|
||||
* [scalaz](generators/scalaz.md)
|
||||
* [swift4-deprecated (deprecated)](generators/swift4-deprecated.md)
|
||||
* [swift5 (beta)](generators/swift5.md)
|
||||
* [typescript (experimental)](generators/typescript.md)
|
||||
* [typescript-angular](generators/typescript-angular.md)
|
||||
* [typescript-angularjs](generators/typescript-angularjs.md)
|
||||
* [typescript-aurelia](generators/typescript-aurelia.md)
|
||||
@@ -104,6 +104,7 @@ The following generators are available:
|
||||
* [kotlin-spring](generators/kotlin-spring.md)
|
||||
* [kotlin-vertx (beta)](generators/kotlin-vertx.md)
|
||||
* [nodejs-express-server (beta)](generators/nodejs-express-server.md)
|
||||
* [nodejs-server-deprecated (deprecated)](generators/nodejs-server-deprecated.md)
|
||||
* [php-laravel](generators/php-laravel.md)
|
||||
* [php-lumen](generators/php-lumen.md)
|
||||
* [php-silex-deprecated (deprecated)](generators/php-silex-deprecated.md)
|
||||
|
||||
@@ -1,142 +1,132 @@
|
||||
---
|
||||
title: Config Options for cpp-ue4
|
||||
sidebar_label: cpp-ue4
|
||||
title: Config Options for typescript
|
||||
sidebar_label: typescript
|
||||
---
|
||||
|
||||
| Option | Description | Values | Default |
|
||||
| ------ | ----------- | ------ | ------- |
|
||||
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
|
||||
|cppNamespace|C++ namespace (convention: name::space::for::api).| |OpenAPI|
|
||||
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|
||||
|fileContentDataType|Specifies the type to use for the content of a file - i.e. Blob (Browser) / Buffer (node)| |Buffer|
|
||||
|framework|Specify the framework which should be used in the client code.|<dl><dt>**fetch-api**</dt><dd>fetch-api</dd><dt>**jquery**</dt><dd>jquery</dd></dl>|fetch-api|
|
||||
|legacyDiscriminatorBehavior|This flag is used by OpenAPITools codegen to influence the processing of the discriminator attribute in OpenAPI documents. This flag has no impact if the OAS document does not use the discriminator attribute. The default value of this flag is set in each language-specific code generator (e.g. Python, Java, go...)using the method toModelName. Note to developers supporting a language generator in OpenAPITools; to fully support the discriminator attribute as defined in the OAS specification 3.x, language generators should set this flag to true by default; however this requires updating the mustache templates to generate a language-specific discriminator lookup function that iterates over {{#mappedModels}} and does not iterate over {{children}}, {{#anyOf}}, or {{#oneOf}}.|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|
||||
|optionalProjectFile|Generate Build.cs| |true|
|
||||
|modelPropertyNaming|Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name| |camelCase|
|
||||
|npmName|The name under which you want to publish generated npm package. Required to generate a full package| |null|
|
||||
|npmRepository|Use this property to set an url your private npmRepo in the package.json| |null|
|
||||
|npmVersion|The version of your npm package. If not provided, using the version from the OpenAPI specification file.| |1.0.0|
|
||||
|platform|Specifies the platform the code should run on. The default is 'node' for the 'request' framework and 'browser' otherwise.|<dl><dt>**browser**</dt><dd>browser</dd><dt>**node**</dt><dd>node</dd></dl>|browser|
|
||||
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|
||||
|reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_|
|
||||
|snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false|
|
||||
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|
||||
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|
||||
|unrealModuleName|Name of the generated unreal module (optional)| |OpenAPI|
|
||||
|variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true|
|
||||
|supportsES6|Generate code that conforms to ES6.| |false|
|
||||
|useRxJS|Enable this to internally use rxjs observables. If disabled, a stub is used instead. This is required for the 'angular' framework.| |false|
|
||||
|
||||
## IMPORT MAPPING
|
||||
|
||||
| Type/Alias | Imports |
|
||||
| ---------- | ------- |
|
||||
|HttpFileInput|#include "OpenAPIHelpers.h"|
|
||||
|
||||
|
||||
## INSTANTIATION TYPES
|
||||
|
||||
| Type/Alias | Instantiated By |
|
||||
| ---------- | --------------- |
|
||||
|array|Array|
|
||||
|
||||
|
||||
## LANGUAGE PRIMITIVES
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>FDateTime</li>
|
||||
<li>FGuid</li>
|
||||
<li>FString</li>
|
||||
<li>TArray</li>
|
||||
<li>TArray<uint8></li>
|
||||
<li>TMap</li>
|
||||
<li>TSharedPtr<FJsonObject></li>
|
||||
<li>bool</li>
|
||||
<li>double</li>
|
||||
<li>float</li>
|
||||
<li>int32</li>
|
||||
<li>int64</li>
|
||||
<li>Array</li>
|
||||
<li>Boolean</li>
|
||||
<li>Date</li>
|
||||
<li>Double</li>
|
||||
<li>Error</li>
|
||||
<li>File</li>
|
||||
<li>Float</li>
|
||||
<li>Integer</li>
|
||||
<li>Long</li>
|
||||
<li>Map</li>
|
||||
<li>Object</li>
|
||||
<li>String</li>
|
||||
<li>any</li>
|
||||
<li>boolean</li>
|
||||
<li>number</li>
|
||||
<li>string</li>
|
||||
</ul>
|
||||
|
||||
## RESERVED WORDS
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>alignas</li>
|
||||
<li>alignof</li>
|
||||
<li>and</li>
|
||||
<li>and_eq</li>
|
||||
<li>asm</li>
|
||||
<li>auto</li>
|
||||
<li>bitand</li>
|
||||
<li>bitor</li>
|
||||
<li>bool</li>
|
||||
<li>abstract</li>
|
||||
<li>await</li>
|
||||
<li>boolean</li>
|
||||
<li>break</li>
|
||||
<li>byte</li>
|
||||
<li>case</li>
|
||||
<li>catch</li>
|
||||
<li>char</li>
|
||||
<li>char16_t</li>
|
||||
<li>char32_t</li>
|
||||
<li>class</li>
|
||||
<li>compl</li>
|
||||
<li>concept</li>
|
||||
<li>const</li>
|
||||
<li>const_cast</li>
|
||||
<li>constexpr</li>
|
||||
<li>continue</li>
|
||||
<li>decltype</li>
|
||||
<li>debugger</li>
|
||||
<li>default</li>
|
||||
<li>delete</li>
|
||||
<li>do</li>
|
||||
<li>double</li>
|
||||
<li>dynamic_cast</li>
|
||||
<li>else</li>
|
||||
<li>enum</li>
|
||||
<li>explicit</li>
|
||||
<li>export</li>
|
||||
<li>extern</li>
|
||||
<li>extends</li>
|
||||
<li>false</li>
|
||||
<li>final</li>
|
||||
<li>finally</li>
|
||||
<li>float</li>
|
||||
<li>for</li>
|
||||
<li>friend</li>
|
||||
<li>formParams</li>
|
||||
<li>function</li>
|
||||
<li>goto</li>
|
||||
<li>headerParams</li>
|
||||
<li>if</li>
|
||||
<li>inline</li>
|
||||
<li>implements</li>
|
||||
<li>import</li>
|
||||
<li>in</li>
|
||||
<li>instanceof</li>
|
||||
<li>int</li>
|
||||
<li>linux</li>
|
||||
<li>interface</li>
|
||||
<li>let</li>
|
||||
<li>long</li>
|
||||
<li>mutable</li>
|
||||
<li>namespace</li>
|
||||
<li>native</li>
|
||||
<li>new</li>
|
||||
<li>noexcept</li>
|
||||
<li>not</li>
|
||||
<li>not_eq</li>
|
||||
<li>nullptr</li>
|
||||
<li>operator</li>
|
||||
<li>or</li>
|
||||
<li>or_eq</li>
|
||||
<li>null</li>
|
||||
<li>package</li>
|
||||
<li>private</li>
|
||||
<li>protected</li>
|
||||
<li>public</li>
|
||||
<li>register</li>
|
||||
<li>reinterpret_cast</li>
|
||||
<li>requires</li>
|
||||
<li>queryParameters</li>
|
||||
<li>requestOptions</li>
|
||||
<li>return</li>
|
||||
<li>short</li>
|
||||
<li>signed</li>
|
||||
<li>sizeof</li>
|
||||
<li>static</li>
|
||||
<li>static_assert</li>
|
||||
<li>static_cast</li>
|
||||
<li>struct</li>
|
||||
<li>super</li>
|
||||
<li>switch</li>
|
||||
<li>template</li>
|
||||
<li>synchronized</li>
|
||||
<li>this</li>
|
||||
<li>thread_local</li>
|
||||
<li>throw</li>
|
||||
<li>transient</li>
|
||||
<li>true</li>
|
||||
<li>try</li>
|
||||
<li>typedef</li>
|
||||
<li>typeid</li>
|
||||
<li>typename</li>
|
||||
<li>union</li>
|
||||
<li>unsigned</li>
|
||||
<li>using</li>
|
||||
<li>virtual</li>
|
||||
<li>typeof</li>
|
||||
<li>useFormData</li>
|
||||
<li>var</li>
|
||||
<li>varLocalDeferred</li>
|
||||
<li>varLocalPath</li>
|
||||
<li>void</li>
|
||||
<li>volatile</li>
|
||||
<li>wchar_t</li>
|
||||
<li>while</li>
|
||||
<li>xor</li>
|
||||
<li>xor_eq</li>
|
||||
<li>with</li>
|
||||
<li>yield</li>
|
||||
</ul>
|
||||
|
||||
## FEATURE SET
|
||||
@@ -30,8 +30,8 @@ public class CodegenOperation {
|
||||
isResponseBinary = false, isResponseFile = false, hasReference = false,
|
||||
isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
|
||||
isRestful, isDeprecated, isCallbackRequest, uniqueItems;
|
||||
public String path, operationId, returnType, httpMethod, returnBaseType,
|
||||
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse;
|
||||
public String path, operationId, returnType, returnFormat, httpMethod, returnBaseType,
|
||||
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse;
|
||||
public CodegenDiscriminator discriminator;
|
||||
public List<Map<String, String>> consumes, produces, prioritizedContentTypes;
|
||||
public List<CodegenServer> servers = new ArrayList<CodegenServer>();
|
||||
|
||||
@@ -3430,8 +3430,9 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
op.examples = new ExampleGenerator(schemas, this.openAPI).generateFromResponseSchema(exampleStatusCode, responseSchema, getProducesInfo(this.openAPI, operation));
|
||||
op.defaultResponse = toDefaultValue(responseSchema);
|
||||
op.returnType = cm.dataType;
|
||||
op.hasReference = schemas.containsKey(op.returnBaseType);
|
||||
|
||||
op.returnFormat = cm.dataFormat;
|
||||
op.hasReference = schemas != null && schemas.containsKey(op.returnBaseType);
|
||||
|
||||
// lookup discriminator
|
||||
Schema schema = schemas.get(op.returnBaseType);
|
||||
if (schema != null) {
|
||||
@@ -4243,7 +4244,7 @@ public class DefaultCodegen implements CodegenConfig {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO revise below as it should be replaced by ModelUtils.isFileSchema(parameterSchema)
|
||||
public boolean isDataTypeFile(String dataType) {
|
||||
if (dataType != null) {
|
||||
|
||||
@@ -30,7 +30,6 @@ import io.swagger.v3.oas.models.parameters.Parameter;
|
||||
import io.swagger.v3.oas.models.security.*;
|
||||
import io.swagger.v3.oas.models.tags.Tag;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.comparator.PathFileComparator;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.config.GlobalSettings;
|
||||
@@ -50,7 +49,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.*;
|
||||
@@ -59,7 +57,6 @@ import static org.openapitools.codegen.utils.OnceLogger.once;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
private static final String METADATA_DIR = ".openapi-generator";
|
||||
protected final Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class);
|
||||
protected CodegenConfig config;
|
||||
protected ClientOptInput opts;
|
||||
@@ -863,7 +860,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
));
|
||||
}
|
||||
|
||||
String versionMetadata = config.outputFolder() + File.separator + METADATA_DIR + File.separator + "VERSION";
|
||||
String versionMetadata = config.outputFolder() + File.separator + ".openapi-generator" + File.separator + "VERSION";
|
||||
if (generateMetadata) {
|
||||
File versionMetadataFile = new File(versionMetadata);
|
||||
try {
|
||||
@@ -933,6 +930,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
bundle.put("hasOAuthMethods", true);
|
||||
bundle.put("oauthMethods", ProcessUtils.getOAuthMethods(authMethods));
|
||||
}
|
||||
|
||||
if (ProcessUtils.hasHttpBearerMethods(authMethods)) {
|
||||
bundle.put("hasHttpBearerMethods", true);
|
||||
}
|
||||
@@ -1059,38 +1057,6 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
sb.append(System.lineSeparator());
|
||||
|
||||
System.err.println(sb.toString());
|
||||
} else {
|
||||
if (generateMetadata) {
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
File outDir = new File(this.config.getOutputDir());
|
||||
|
||||
List<File> filesToSort = new ArrayList<>();
|
||||
|
||||
// Avoid side-effecting sort in this path when generateMetadata=true
|
||||
files.forEach(f -> {
|
||||
// We have seen NPE on CI for getPath() returning null, so guard against this (to be fixed in 5.0 template management refactor)
|
||||
//noinspection ConstantConditions
|
||||
if (f != null && f.getPath() != null) {
|
||||
filesToSort.add(f);
|
||||
}
|
||||
});
|
||||
|
||||
filesToSort.sort(PathFileComparator.PATH_COMPARATOR);
|
||||
filesToSort.forEach(f -> {
|
||||
String relativePath = outDir.toPath().relativize(f.toPath()).toString();
|
||||
if (!relativePath.equals(METADATA_DIR + File.separator + "VERSION")) {
|
||||
sb.append(relativePath).append(System.lineSeparator());
|
||||
}
|
||||
});
|
||||
|
||||
String targetFile = config.outputFolder() + File.separator + METADATA_DIR + File.separator + "FILES";
|
||||
File filesFile = writeToFile(targetFile, sb.toString().getBytes(StandardCharsets.UTF_8));
|
||||
files.add(filesFile);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Failed to write FILES metadata to track generated files.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset GlobalSettings, so that the running thread can be reused for another generator-run
|
||||
@@ -1479,6 +1445,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected File writeInputStreamToFile(String filename, InputStream in, String templateFile) throws IOException {
|
||||
if (in != null) {
|
||||
byte[] bytes = IOUtils.toByteArray(in);
|
||||
|
||||
@@ -164,7 +164,6 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
|
||||
typeMapping.put("UUID", "string");
|
||||
typeMapping.put("URI", "string");
|
||||
typeMapping.put("Error", "Error");
|
||||
typeMapping.put("AnyType", "any");
|
||||
|
||||
cliOptions.add(new CliOption(CodegenConstants.ENUM_NAME_SUFFIX, CodegenConstants.ENUM_NAME_SUFFIX_DESC).defaultValue(this.enumSuffix));
|
||||
cliOptions.add(new CliOption(CodegenConstants.ENUM_PROPERTY_NAMING, CodegenConstants.ENUM_PROPERTY_NAMING_DESC).defaultValue(this.enumPropertyNaming.name()));
|
||||
@@ -809,38 +808,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
|
||||
|
||||
@Override
|
||||
public String toAnyOfName(List<String> names, ComposedSchema composedSchema) {
|
||||
List<String> types = getTypesFromSchemas(composedSchema.getAnyOf());
|
||||
|
||||
return String.join(" | ", types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOneOfName(List<String> names, ComposedSchema composedSchema) {
|
||||
List<String> types = getTypesFromSchemas(composedSchema.getOneOf());
|
||||
|
||||
return String.join(" | ", types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toAllOfName(List<String> names, ComposedSchema composedSchema) {
|
||||
List<String> types = getTypesFromSchemas(composedSchema.getAllOf());
|
||||
|
||||
return String.join(" & ", types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the list of type names from a list of schemas.
|
||||
* Excludes `AnyType` if there are other valid types extracted.
|
||||
*
|
||||
* @param schemas list of schemas
|
||||
* @return list of types
|
||||
*/
|
||||
protected List<String> getTypesFromSchemas(List<Schema> schemas) {
|
||||
List<Schema> filteredSchemas = schemas.size() > 1
|
||||
? schemas.stream().filter(schema -> super.getSchemaType(schema) != "AnyType").collect(Collectors.toList())
|
||||
: schemas;
|
||||
|
||||
return filteredSchemas.stream().map(schema -> {
|
||||
List<String> types = composedSchema.getAnyOf().stream().map(schema -> {
|
||||
String schemaType = getSchemaType(schema);
|
||||
if (ModelUtils.isArraySchema(schema)) {
|
||||
ArraySchema ap = (ArraySchema) schema;
|
||||
@@ -849,5 +817,34 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
|
||||
}
|
||||
return schemaType;
|
||||
}).distinct().collect(Collectors.toList());
|
||||
return String.join(" | ", types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOneOfName(List<String> names, ComposedSchema composedSchema) {
|
||||
List<String> types = composedSchema.getOneOf().stream().map(schema -> {
|
||||
String schemaType = getSchemaType(schema);
|
||||
if (ModelUtils.isArraySchema(schema)) {
|
||||
ArraySchema ap = (ArraySchema) schema;
|
||||
Schema inner = ap.getItems();
|
||||
schemaType = schemaType + "<" + getSchemaType(inner) + ">";
|
||||
}
|
||||
return schemaType;
|
||||
}).distinct().collect(Collectors.toList());
|
||||
return String.join(" | ", types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toAllOfName(List<String> names, ComposedSchema composedSchema) {
|
||||
List<String> types = composedSchema.getAllOf().stream().map(schema -> {
|
||||
String schemaType = getSchemaType(schema);
|
||||
if (ModelUtils.isArraySchema(schema)) {
|
||||
ArraySchema ap = (ArraySchema) schema;
|
||||
Schema inner = ap.getItems();
|
||||
schemaType = schemaType + "<" + getSchemaType(inner) + ">";
|
||||
}
|
||||
return schemaType;
|
||||
}).distinct().collect(Collectors.toList());
|
||||
return String.join(" & ", types);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,544 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.meta.GeneratorMetadata;
|
||||
import org.openapitools.codegen.meta.Stability;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static org.openapitools.codegen.utils.StringUtils.camelize;
|
||||
|
||||
public class CppUE4ClientCodegen extends AbstractCppCodegen {
|
||||
public static final String CPP_NAMESPACE = "cppNamespace";
|
||||
public static final String CPP_NAMESPACE_DESC = "C++ namespace (convention: name::space::for::api).";
|
||||
public static final String UNREAL_MODULE_NAME = "unrealModuleName";
|
||||
public static final String UNREAL_MODULE_NAME_DESC = "Name of the generated unreal module (optional)";
|
||||
public static final String OPTIONAL_PROJECT_FILE_DESC = "Generate Build.cs";
|
||||
|
||||
protected String unrealModuleName = "OpenAPI";
|
||||
// Will be treated as pointer
|
||||
protected Set<String> pointerClasses = new HashSet<String>();
|
||||
// source folder where to write the files
|
||||
protected String privateFolder = "Private";
|
||||
protected String publicFolder = "Public";
|
||||
protected String apiVersion = "1.0.0";
|
||||
protected Map<String, String> namespaces = new HashMap<String, String>();
|
||||
// Will be included using the <> syntax, not used in Unreal's coding convention
|
||||
protected Set<String> systemIncludes = new HashSet<String>();
|
||||
protected String cppNamespace = unrealModuleName;
|
||||
protected boolean optionalProjectFileFlag = true;
|
||||
|
||||
public CppUE4ClientCodegen() {
|
||||
super();
|
||||
|
||||
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
|
||||
.stability(Stability.BETA)
|
||||
.build();
|
||||
|
||||
// set the output folder here
|
||||
outputFolder = "generated-code/cpp-ue4";
|
||||
|
||||
// set modelNamePrefix as default for cpp-ue4
|
||||
if ("".equals(modelNamePrefix)) {
|
||||
modelNamePrefix = unrealModuleName;
|
||||
}
|
||||
|
||||
/*
|
||||
* Models. You can write model files using the modelTemplateFiles map.
|
||||
* if you want to create one template for file, you can do so here.
|
||||
* for multiple files for model, just put another entry in the `modelTemplateFiles` with
|
||||
* a different extension
|
||||
*/
|
||||
modelTemplateFiles.put(
|
||||
"model-header.mustache",
|
||||
".h");
|
||||
|
||||
modelTemplateFiles.put(
|
||||
"model-source.mustache",
|
||||
".cpp");
|
||||
|
||||
/*
|
||||
* Api classes. You can write classes for each Api file with the apiTemplateFiles map.
|
||||
* as with models, add multiple entries with different extensions for multiple files per
|
||||
* class
|
||||
*/
|
||||
apiTemplateFiles.put(
|
||||
"api-header.mustache", // the template to use
|
||||
".h"); // the extension for each file to write
|
||||
|
||||
apiTemplateFiles.put(
|
||||
"api-source.mustache", // the template to use
|
||||
".cpp"); // the extension for each file to write
|
||||
|
||||
apiTemplateFiles.put(
|
||||
"api-operations-header.mustache", // the template to use
|
||||
".h"); // the extension for each file to write
|
||||
|
||||
apiTemplateFiles.put(
|
||||
"api-operations-source.mustache", // the template to use
|
||||
".cpp"); // the extension for each file to write
|
||||
|
||||
/*
|
||||
* Template Location. This is the location which templates will be read from. The generator
|
||||
* will use the resource stream to attempt to read the templates.
|
||||
*/
|
||||
embeddedTemplateDir = templateDir = "cpp-ue4";
|
||||
|
||||
// CLI options
|
||||
addOption(CPP_NAMESPACE, CPP_NAMESPACE_DESC, this.cppNamespace);
|
||||
addOption(UNREAL_MODULE_NAME, UNREAL_MODULE_NAME_DESC, this.unrealModuleName);
|
||||
addSwitch(CodegenConstants.OPTIONAL_PROJECT_FILE, OPTIONAL_PROJECT_FILE_DESC, this.optionalProjectFileFlag);
|
||||
|
||||
/*
|
||||
* Additional Properties. These values can be passed to the templates and
|
||||
* are available in models, apis, and supporting files
|
||||
*/
|
||||
additionalProperties.put("apiVersion", apiVersion);
|
||||
additionalProperties().put("modelNamePrefix", modelNamePrefix);
|
||||
additionalProperties().put("modelPackage", modelPackage);
|
||||
additionalProperties().put("apiPackage", apiPackage);
|
||||
additionalProperties().put("dllapi", unrealModuleName.toUpperCase(Locale.ROOT) + "_API");
|
||||
additionalProperties().put("unrealModuleName", unrealModuleName);
|
||||
|
||||
// Write defaults namespace in properties so that it can be accessible in templates.
|
||||
// At this point command line has not been parsed so if value is given
|
||||
// in command line it will superseed this content
|
||||
additionalProperties.put("cppNamespace", cppNamespace);
|
||||
additionalProperties.put("unrealModuleName", unrealModuleName);
|
||||
|
||||
/*
|
||||
* Language Specific Primitives. These types will not trigger imports by
|
||||
* the client generator
|
||||
*/
|
||||
languageSpecificPrimitives = new HashSet<String>(
|
||||
Arrays.asList(
|
||||
"bool",
|
||||
"int32",
|
||||
"int64",
|
||||
"float",
|
||||
"double",
|
||||
"FString",
|
||||
"FDateTime",
|
||||
"FGuid",
|
||||
"TArray",
|
||||
"TArray<uint8>", // For byte arrays
|
||||
"TMap",
|
||||
"TSharedPtr<FJsonObject>")
|
||||
);
|
||||
|
||||
supportingFiles.add(new SupportingFile("model-base-header.mustache", publicFolder, modelNamePrefix + "BaseModel.h"));
|
||||
supportingFiles.add(new SupportingFile("model-base-source.mustache", privateFolder, modelNamePrefix + "BaseModel.cpp"));
|
||||
supportingFiles.add(new SupportingFile("helpers-header.mustache", publicFolder, modelNamePrefix + "Helpers.h"));
|
||||
supportingFiles.add(new SupportingFile("helpers-source.mustache", privateFolder, modelNamePrefix + "Helpers.cpp"));
|
||||
if (optionalProjectFileFlag) {
|
||||
supportingFiles.add(new SupportingFile("Build.cs.mustache", unrealModuleName + ".Build.cs"));
|
||||
supportingFiles.add(new SupportingFile("module-header.mustache", privateFolder, unrealModuleName + "Module.h"));
|
||||
supportingFiles.add(new SupportingFile("module-source.mustache", privateFolder, unrealModuleName + "Module.cpp"));
|
||||
}
|
||||
|
||||
super.typeMapping = new HashMap<String, String>();
|
||||
|
||||
// Maps C++ types during call to getSchemaType, see DefaultCodegen.getSchemaType and not the types/formats
|
||||
// defined in openapi specification "array" is also used explicitly in the generator for containers
|
||||
typeMapping.clear();
|
||||
typeMapping.put("integer", "int32");
|
||||
typeMapping.put("long", "int64");
|
||||
typeMapping.put("float", "float");
|
||||
typeMapping.put("number", "double");
|
||||
typeMapping.put("double", "double");
|
||||
typeMapping.put("string", "FString");
|
||||
typeMapping.put("byte", "uint8");
|
||||
typeMapping.put("binary", "TArray<uint8>");
|
||||
typeMapping.put("ByteArray", "TArray<uint8>");
|
||||
typeMapping.put("password", "FString");
|
||||
typeMapping.put("boolean", "bool");
|
||||
typeMapping.put("date", "FDateTime");
|
||||
typeMapping.put("Date", "FDateTime");
|
||||
typeMapping.put("date-time", "FDateTime");
|
||||
typeMapping.put("DateTime", "FDateTime");
|
||||
typeMapping.put("array", "TArray");
|
||||
typeMapping.put("list", "TArray");
|
||||
typeMapping.put("map", "TMap");
|
||||
typeMapping.put("object", "TSharedPtr<FJsonObject>");
|
||||
typeMapping.put("Object", "TSharedPtr<FJsonObject>");
|
||||
typeMapping.put("file", "HttpFileInput");
|
||||
typeMapping.put("UUID", "FGuid");
|
||||
|
||||
importMapping = new HashMap<String, String>();
|
||||
importMapping.put("HttpFileInput", "#include \"" + modelNamePrefix + "Helpers.h\"");
|
||||
|
||||
namespaces = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey("cppNamespace")) {
|
||||
cppNamespace = (String) additionalProperties.get("cppNamespace");
|
||||
}
|
||||
|
||||
additionalProperties.put("cppNamespaceDeclarations", cppNamespace.split("\\::"));
|
||||
|
||||
boolean updateSupportingFiles = false;
|
||||
if (additionalProperties.containsKey("unrealModuleName")) {
|
||||
unrealModuleName = (String) additionalProperties.get("unrealModuleName");
|
||||
additionalProperties().put("dllapi", unrealModuleName.toUpperCase(Locale.ROOT) + "_API");
|
||||
modelNamePrefix = unrealModuleName;
|
||||
updateSupportingFiles = true;
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey("modelNamePrefix")) {
|
||||
modelNamePrefix = (String) additionalProperties.get("modelNamePrefix");
|
||||
updateSupportingFiles = true;
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) {
|
||||
setOptionalProjectFileFlag(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_PROJECT_FILE));
|
||||
} else {
|
||||
additionalProperties.put(CodegenConstants.OPTIONAL_PROJECT_FILE, optionalProjectFileFlag);
|
||||
}
|
||||
|
||||
if (updateSupportingFiles) {
|
||||
supportingFiles.clear();
|
||||
|
||||
supportingFiles.add(new SupportingFile("model-base-header.mustache", publicFolder, modelNamePrefix + "BaseModel.h"));
|
||||
supportingFiles.add(new SupportingFile("model-base-source.mustache", privateFolder, modelNamePrefix + "BaseModel.cpp"));
|
||||
supportingFiles.add(new SupportingFile("helpers-header.mustache", publicFolder, modelNamePrefix + "Helpers.h"));
|
||||
supportingFiles.add(new SupportingFile("helpers-source.mustache", privateFolder, modelNamePrefix + "Helpers.cpp"));
|
||||
if (optionalProjectFileFlag) {
|
||||
supportingFiles.add(new SupportingFile("Build.cs.mustache", unrealModuleName + ".Build.cs"));
|
||||
supportingFiles.add(new SupportingFile("module-header.mustache", privateFolder, unrealModuleName + "Module.h"));
|
||||
supportingFiles.add(new SupportingFile("module-source.mustache", privateFolder, unrealModuleName + "Module.cpp"));
|
||||
}
|
||||
|
||||
importMapping.put("HttpFileInput", "#include \"" + modelNamePrefix + "Helpers.h\"");
|
||||
}
|
||||
}
|
||||
|
||||
public void setOptionalProjectFileFlag(boolean flag) {
|
||||
this.optionalProjectFileFlag = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*/
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the generator
|
||||
* to select the library with the -l flag.
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "cpp-ue4";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with help
|
||||
* tips, parameters here
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a Unreal Engine 4 C++ Module (beta).";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
if (namespaces.containsKey(name)) {
|
||||
return "using " + namespaces.get(name) + ";";
|
||||
} else if (systemIncludes.contains(name)) {
|
||||
return "#include <" + name + ">";
|
||||
}
|
||||
|
||||
String folder = modelPackage().replace("::", File.separator);
|
||||
if (!folder.isEmpty())
|
||||
folder += File.separator;
|
||||
|
||||
return "#include \"" + folder + name + ".h\"";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needToImport(String type) {
|
||||
boolean shouldImport = super.needToImport(type);
|
||||
if (shouldImport)
|
||||
return !languageSpecificPrimitives.contains(type);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
|
||||
* those terms here. This logic is only called if a variable matches the reserved words
|
||||
*
|
||||
* @return the escaped term
|
||||
*/
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write model files. You can use the modelPackage() as defined when the class is
|
||||
* instantiated
|
||||
*/
|
||||
@Override
|
||||
public String modelFileFolder() {
|
||||
return outputFolder + File.separator + modelPackage().replace("::", File.separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when the class is
|
||||
* instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + apiPackage().replace("::", File.separator);
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public String modelFilename(String templateName, String tag) {
|
||||
String suffix = modelTemplateFiles().get(templateName);
|
||||
String folder = privateFolder;
|
||||
if (suffix == ".h") {
|
||||
folder = publicFolder;
|
||||
}
|
||||
|
||||
return modelFileFolder() + File.separator + folder + File.separator + toModelFilename(tag) + suffix;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
name = sanitizeName(name);
|
||||
return modelNamePrefix + camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFilename(String templateName, String tag) {
|
||||
String suffix = apiTemplateFiles().get(templateName);
|
||||
String folder = privateFolder;
|
||||
if (".h".equals(suffix)) {
|
||||
folder = publicFolder;
|
||||
}
|
||||
|
||||
if (templateName.startsWith("api-operations")) {
|
||||
return apiFileFolder() + File.separator + folder + File.separator + toApiFilename(tag) + "Operations" + suffix;
|
||||
} else {
|
||||
return apiFileFolder() + File.separator + folder + File.separator + toApiFilename(tag) + suffix;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
name = sanitizeName(name);
|
||||
return modelNamePrefix + camelize(name) + "Api";
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - type declaration. This is a String which is used by the templates to instantiate your
|
||||
* types. There is typically special handling for different property types
|
||||
*
|
||||
* @return a string value used as the `dataType` field for model templates, `returnType` for api templates
|
||||
*/
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
String openAPIType = getSchemaType(p);
|
||||
|
||||
if (ModelUtils.isArraySchema(p)) {
|
||||
ArraySchema ap = (ArraySchema) p;
|
||||
String inner = getSchemaType(ap.getItems());
|
||||
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
String inner = getSchemaType(ModelUtils.getAdditionalProperties(p));
|
||||
return getSchemaType(p) + "<FString, " + getTypeDeclaration(inner) + ">";
|
||||
}
|
||||
|
||||
if (pointerClasses.contains(openAPIType)) {
|
||||
return openAPIType + "*";
|
||||
} else if (languageSpecificPrimitives.contains(openAPIType)) {
|
||||
return toModelName(openAPIType);
|
||||
} else {
|
||||
return openAPIType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (ModelUtils.isStringSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return "TEXT(\"" + p.getDefault().toString() + "\")";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (ModelUtils.isBooleanSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
} else if (ModelUtils.isDateSchema(p)) {
|
||||
return "FDateTime(0)";
|
||||
} else if (ModelUtils.isDateTimeSchema(p)) {
|
||||
return "FDateTime(0)";
|
||||
} else if (ModelUtils.isDoubleSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "0.0";
|
||||
}
|
||||
} else if (ModelUtils.isFloatSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "0.0f";
|
||||
}
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
} else if (ModelUtils.isLongSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional - OpenAPI type conversion. This is used to map OpenAPI types in a `Property` into
|
||||
* either language specific types via `typeMapping` or into complex models if there is not a mapping.
|
||||
*
|
||||
* @return a string value of the type or complex model for this property
|
||||
* @see io.swagger.v3.oas.models.media.Schema
|
||||
*/
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return toModelName(type);
|
||||
}
|
||||
if (pointerClasses.contains(type)) {
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String type) {
|
||||
if (typeMapping.keySet().contains(type) ||
|
||||
typeMapping.values().contains(type) ||
|
||||
importMapping.values().contains(type) ||
|
||||
defaultIncludes.contains(type) ||
|
||||
languageSpecificPrimitives.contains(type)) {
|
||||
return type;
|
||||
} else {
|
||||
return modelNamePrefix + camelize(sanitizeName(type), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
|
||||
// if it's all uppper case, convert to lower case
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
name = name.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(name) || name.matches("^\\d.*")) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
|
||||
//Unreal variable names are CamelCase
|
||||
return camelize(name, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String name, String datatype) {
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String type) {
|
||||
return modelNamePrefix + camelize(type, false) + "Api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
public String toBooleanGetter(String name) {
|
||||
return "Is" + getterAndSetterCapitalize(name);
|
||||
}
|
||||
|
||||
public String toGetter(String name) {
|
||||
return "Get" + getterAndSetterCapitalize(name);
|
||||
}
|
||||
|
||||
public String toSetter(String name) {
|
||||
return "Set" + getterAndSetterCapitalize(name);
|
||||
}
|
||||
}
|
||||
@@ -380,9 +380,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
|
||||
} else if (JERSEY2.equals(getLibrary())) {
|
||||
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
|
||||
supportingFiles.add(new SupportingFile("ApiResponse.mustache", invokerFolder, "ApiResponse.java"));
|
||||
if (ProcessUtils.hasHttpSignatureMethods(openAPI)) {
|
||||
supportingFiles.add(new SupportingFile("auth/HttpSignatureAuth.mustache", authFolder, "HttpSignatureAuth.java"));
|
||||
}
|
||||
supportingFiles.add(new SupportingFile("auth/HttpSignatureAuth.mustache", authFolder, "HttpSignatureAuth.java"));
|
||||
supportingFiles.add(new SupportingFile("AbstractOpenApiSchema.mustache", (sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar), "AbstractOpenApiSchema.java"));
|
||||
forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
|
||||
} else if (NATIVE.equals(getLibrary())) {
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
* Copyright 2018 SmartBear Software
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.PathItem;
|
||||
import io.swagger.v3.oas.models.PathItem.HttpMethod;
|
||||
import io.swagger.v3.oas.models.Paths;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.config.GlobalSettings;
|
||||
import org.openapitools.codegen.meta.GeneratorMetadata;
|
||||
import org.openapitools.codegen.meta.Stability;
|
||||
import org.openapitools.codegen.meta.features.*;
|
||||
import org.openapitools.codegen.utils.URLPathUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.openapitools.codegen.utils.StringUtils.*;
|
||||
|
||||
public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NodeJSServerCodegen.class);
|
||||
protected String implFolder = "service";
|
||||
public static final String GOOGLE_CLOUD_FUNCTIONS = "googleCloudFunctions";
|
||||
public static final String EXPORTED_NAME = "exportedName";
|
||||
public static final String SERVER_PORT = "serverPort";
|
||||
|
||||
protected String apiVersion = "1.0.0";
|
||||
protected String projectName = "openapi-server";
|
||||
protected String defaultServerPort = "8080";
|
||||
|
||||
protected boolean googleCloudFunctions;
|
||||
protected String exportedName;
|
||||
|
||||
public NodeJSServerCodegen() {
|
||||
super();
|
||||
|
||||
modifyFeatureSet(features -> features
|
||||
.includeDocumentationFeatures(DocumentationFeature.Readme)
|
||||
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON))
|
||||
.securityFeatures(EnumSet.noneOf(SecurityFeature.class))
|
||||
.excludeGlobalFeatures(
|
||||
GlobalFeature.XMLStructureDefinitions,
|
||||
GlobalFeature.Callbacks,
|
||||
GlobalFeature.LinkObjects,
|
||||
GlobalFeature.ParameterStyling
|
||||
)
|
||||
.excludeSchemaSupportFeatures(
|
||||
SchemaSupportFeature.Polymorphism
|
||||
)
|
||||
.excludeParameterFeatures(
|
||||
ParameterFeature.Cookie
|
||||
)
|
||||
);
|
||||
|
||||
// mark the generator as deprecated in the documentation
|
||||
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
|
||||
.stability(Stability.DEPRECATED)
|
||||
.build();
|
||||
|
||||
// set the output folder here
|
||||
outputFolder = "generated-code/nodejs";
|
||||
|
||||
/*
|
||||
* Models. You can write model files using the modelTemplateFiles map.
|
||||
* if you want to create one template for file, you can do so here.
|
||||
* for multiple files for model, just put another entry in the `modelTemplateFiles` with
|
||||
* a different extension
|
||||
*/
|
||||
modelTemplateFiles.clear();
|
||||
|
||||
/*
|
||||
* Api classes. You can write classes for each Api file with the apiTemplateFiles map.
|
||||
* as with models, add multiple entries with different extensions for multiple files per
|
||||
* class
|
||||
*/
|
||||
apiTemplateFiles.put(
|
||||
"controller.mustache", // the template to use
|
||||
".js"); // the extension for each file to write
|
||||
|
||||
/*
|
||||
* Template Location. This is the location which templates will be read from. The generator
|
||||
* will use the resource stream to attempt to read the templates.
|
||||
*/
|
||||
embeddedTemplateDir = templateDir = "nodejs";
|
||||
|
||||
/*
|
||||
* Reserved words. Override this with reserved words specific to your language
|
||||
*/
|
||||
setReservedWordsLowerCase(
|
||||
Arrays.asList(
|
||||
"break", "case", "class", "catch", "const", "continue", "debugger",
|
||||
"default", "delete", "do", "else", "enum", "export", "extends", "finally",
|
||||
"for", "function", "if", "import", "in", "instanceof", "let", "new",
|
||||
"return", "super", "switch", "this", "throw", "try", "typeof", "var",
|
||||
"void", "while", "with", "yield")
|
||||
);
|
||||
|
||||
/*
|
||||
* Additional Properties. These values can be passed to the templates and
|
||||
* are available in models, apis, and supporting files
|
||||
*/
|
||||
additionalProperties.put("apiVersion", apiVersion);
|
||||
additionalProperties.put("implFolder", implFolder);
|
||||
|
||||
supportingFiles.add(new SupportingFile("writer.mustache", ("utils").replace(".", File.separator), "writer.js"));
|
||||
|
||||
cliOptions.add(CliOption.newBoolean(GOOGLE_CLOUD_FUNCTIONS,
|
||||
"When specified, it will generate the code which runs within Google Cloud Functions "
|
||||
+ "instead of standalone Node.JS server. See "
|
||||
+ "https://cloud.google.com/functions/docs/quickstart for the details of how to "
|
||||
+ "deploy the generated code."));
|
||||
cliOptions.add(new CliOption(EXPORTED_NAME,
|
||||
"When the generated code will be deployed to Google Cloud Functions, this option can be "
|
||||
+ "used to update the name of the exported function. By default, it refers to the "
|
||||
+ "basePath. This does not affect normal standalone nodejs server code."));
|
||||
cliOptions.add(new CliOption(SERVER_PORT,
|
||||
"TCP port to listen on."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiPackage() {
|
||||
return "controllers";
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the type of generator.
|
||||
*
|
||||
* @return the CodegenType for this generator
|
||||
* @see org.openapitools.codegen.CodegenType
|
||||
*/
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a friendly name for the generator. This will be used by the generator
|
||||
* to select the library with the -g flag.
|
||||
*
|
||||
* @return the friendly name for the generator
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "nodejs-server-deprecated";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns human-friendly help for the generator. Provide the consumer with help
|
||||
* tips, parameters here
|
||||
*
|
||||
* @return A string value for the help message
|
||||
*/
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "[DEPRECATED] Generates a nodejs server library using the swagger-tools project. By default, " +
|
||||
"it will also generate service classes--which you can disable with the `-Dnoservice` environment variable.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiName(String name) {
|
||||
if (name.length() == 0) {
|
||||
return "DefaultController";
|
||||
}
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiFilename(String name) {
|
||||
return toApiName(name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apiFilename(String templateName, String tag) {
|
||||
String result = super.apiFilename(templateName, tag);
|
||||
|
||||
if (templateName.equals("service.mustache")) {
|
||||
String stringToMatch = File.separator + "controllers" + File.separator;
|
||||
String replacement = File.separator + implFolder + File.separator;
|
||||
result = result.replaceAll(Pattern.quote(stringToMatch), replacement);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String implFileFolder(String output) {
|
||||
return outputFolder + File.separator + output + File.separator + apiPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
|
||||
* those terms here. This logic is only called if a variable matches the reserved words
|
||||
*
|
||||
* @return the escaped term
|
||||
*/
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to write api files. You can use the apiPackage() as defined when the class is
|
||||
* instantiated
|
||||
*/
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar);
|
||||
}
|
||||
|
||||
public boolean getGoogleCloudFunctions() {
|
||||
return googleCloudFunctions;
|
||||
}
|
||||
|
||||
public void setGoogleCloudFunctions(boolean value) {
|
||||
googleCloudFunctions = value;
|
||||
}
|
||||
|
||||
public String getExportedName() {
|
||||
return exportedName;
|
||||
}
|
||||
|
||||
public void setExportedName(String name) {
|
||||
exportedName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
|
||||
for (CodegenOperation operation : operations) {
|
||||
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);
|
||||
|
||||
List<CodegenParameter> params = operation.allParams;
|
||||
if (params != null && params.size() == 0) {
|
||||
operation.allParams = null;
|
||||
}
|
||||
List<CodegenResponse> responses = operation.responses;
|
||||
if (responses != null) {
|
||||
for (CodegenResponse resp : responses) {
|
||||
if ("0".equals(resp.code)) {
|
||||
resp.code = "default";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (operation.examples != null && !operation.examples.isEmpty()) {
|
||||
// Leave application/json* items only
|
||||
for (Iterator<Map<String, String>> it = operation.examples.iterator(); it.hasNext(); ) {
|
||||
final Map<String, String> example = it.next();
|
||||
final String contentType = example.get("contentType");
|
||||
if (contentType == null || !contentType.startsWith("application/json")) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<Map<String, Object>> getOperations(Map<String, Object> objs) {
|
||||
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
|
||||
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
|
||||
List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis");
|
||||
for (Map<String, Object> api : apis) {
|
||||
result.add((Map<String, Object>) api.get("operations"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<Map<String, Object>> sortOperationsByPath(List<CodegenOperation> ops) {
|
||||
Multimap<String, CodegenOperation> opsByPath = ArrayListMultimap.create();
|
||||
|
||||
for (CodegenOperation op : ops) {
|
||||
opsByPath.put(op.path, op);
|
||||
}
|
||||
|
||||
List<Map<String, Object>> opsByPathList = new ArrayList<Map<String, Object>>();
|
||||
for (Entry<String, Collection<CodegenOperation>> entry : opsByPath.asMap().entrySet()) {
|
||||
Map<String, Object> opsByPathEntry = new HashMap<String, Object>();
|
||||
opsByPathList.add(opsByPathEntry);
|
||||
opsByPathEntry.put("path", entry.getKey());
|
||||
opsByPathEntry.put("operation", entry.getValue());
|
||||
List<CodegenOperation> operationsForThisPath = Lists.newArrayList(entry.getValue());
|
||||
operationsForThisPath.get(operationsForThisPath.size() - 1).hasMore = false;
|
||||
if (opsByPathList.size() < opsByPath.asMap().size()) {
|
||||
opsByPathEntry.put("hasMore", "true");
|
||||
}
|
||||
}
|
||||
|
||||
return opsByPathList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append(System.lineSeparator()).append(System.lineSeparator())
|
||||
.append("=======================================================================================")
|
||||
.append(System.lineSeparator())
|
||||
.append("IMPORTANT: The nodejs-server generator has been deprecated.")
|
||||
.append(System.lineSeparator())
|
||||
.append("Currently, Node.js server doesn't work as its dependency doesn't support OpenAPI Spec3.")
|
||||
.append(System.lineSeparator())
|
||||
.append("For further details, see https://github.com/OpenAPITools/openapi-generator/issues/34")
|
||||
.append(System.lineSeparator())
|
||||
.append("=======================================================================================")
|
||||
.append(System.lineSeparator()).append(System.lineSeparator());
|
||||
LOGGER.warn(message.toString());
|
||||
|
||||
if (additionalProperties.containsKey(GOOGLE_CLOUD_FUNCTIONS)) {
|
||||
setGoogleCloudFunctions(
|
||||
Boolean.valueOf(additionalProperties.get(GOOGLE_CLOUD_FUNCTIONS).toString()));
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(EXPORTED_NAME)) {
|
||||
setExportedName((String) additionalProperties.get(EXPORTED_NAME));
|
||||
}
|
||||
|
||||
/*
|
||||
* Supporting Files. You can write single files for the generator with the
|
||||
* entire object tree available. If the input file has a suffix of `.mustache
|
||||
* it will be processed by the template engine. Otherwise, it will be copied
|
||||
*/
|
||||
// supportingFiles.add(new SupportingFile("controller.mustache",
|
||||
// "controllers",
|
||||
// "controller.js")
|
||||
// );
|
||||
supportingFiles.add(new SupportingFile("openapi.mustache",
|
||||
"api",
|
||||
"openapi.yaml")
|
||||
);
|
||||
if (getGoogleCloudFunctions()) {
|
||||
supportingFiles.add(new SupportingFile("index-gcf.mustache", "", "index.js")
|
||||
.doNotOverwrite());
|
||||
} else {
|
||||
supportingFiles.add(new SupportingFile("index.mustache", "", "index.js")
|
||||
.doNotOverwrite());
|
||||
}
|
||||
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json")
|
||||
.doNotOverwrite());
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")
|
||||
.doNotOverwrite());
|
||||
if (GlobalSettings.getProperty("noservice") == null) {
|
||||
apiTemplateFiles.put(
|
||||
"service.mustache", // the template to use
|
||||
"Service.js"); // the extension for each file to write
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocessOpenAPI(OpenAPI openAPI) {
|
||||
URL url = URLPathUtils.getServerURL(openAPI, serverVariableOverrides());
|
||||
String host = URLPathUtils.getProtocolAndHost(url);
|
||||
String port = URLPathUtils.getPort(url, defaultServerPort) ;
|
||||
String basePath = url.getPath();
|
||||
|
||||
if (additionalProperties.containsKey(SERVER_PORT)) {
|
||||
port = additionalProperties.get(SERVER_PORT).toString();
|
||||
}
|
||||
this.additionalProperties.put(SERVER_PORT, port);
|
||||
|
||||
if (openAPI.getInfo() != null) {
|
||||
Info info = openAPI.getInfo();
|
||||
if (info.getTitle() != null) {
|
||||
// when info.title is defined, use it for projectName
|
||||
// used in package.json
|
||||
projectName = info.getTitle()
|
||||
.replaceAll("[^a-zA-Z0-9]", "-")
|
||||
.replaceAll("^[-]*", "")
|
||||
.replaceAll("[-]*$", "")
|
||||
.replaceAll("[-]{2,}", "-")
|
||||
.toLowerCase(Locale.ROOT);
|
||||
this.additionalProperties.put("projectName", projectName);
|
||||
}
|
||||
}
|
||||
|
||||
if (getGoogleCloudFunctions()) {
|
||||
// Note that Cloud Functions don't allow customizing port name, simply checking host
|
||||
// is good enough.
|
||||
if (!host.endsWith(".cloudfunctions.net")) {
|
||||
LOGGER.warn("Host " + host + " seems not matching with cloudfunctions.net URL.");
|
||||
}
|
||||
if (!additionalProperties.containsKey(EXPORTED_NAME)) {
|
||||
if (basePath == null || basePath.equals("/")) {
|
||||
LOGGER.warn("Cannot find the exported name properly. Using 'openapi' as the exported name");
|
||||
basePath = "/openapi";
|
||||
}
|
||||
additionalProperties.put(EXPORTED_NAME, basePath.substring(1));
|
||||
}
|
||||
}
|
||||
|
||||
// need vendor extensions for x-swagger-router-controller
|
||||
Paths paths = openAPI.getPaths();
|
||||
if (paths != null) {
|
||||
for (String pathname : paths.keySet()) {
|
||||
PathItem path = paths.get(pathname);
|
||||
Map<HttpMethod, Operation> operationMap = path.readOperationsMap();
|
||||
if (operationMap != null) {
|
||||
for (HttpMethod method : operationMap.keySet()) {
|
||||
Operation operation = operationMap.get(method);
|
||||
String tag = "default";
|
||||
if (operation.getTags() != null && operation.getTags().size() > 0) {
|
||||
tag = toApiName(operation.getTags().get(0));
|
||||
}
|
||||
if (operation.getOperationId() == null) {
|
||||
operation.setOperationId(getOrGenerateOperationId(operation, pathname, method.toString()));
|
||||
}
|
||||
if (operation.getExtensions() == null ||
|
||||
operation.getExtensions().get("x-swagger-router-controller") == null) {
|
||||
operation.addExtension("x-swagger-router-controller", sanitizeTag(tag));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
|
||||
generateYAMLSpecFile(objs);
|
||||
|
||||
for (Map<String, Object> operations : getOperations(objs)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
|
||||
|
||||
List<Map<String, Object>> opsByPathList = sortOperationsByPath(ops);
|
||||
operations.put("operationsByPath", opsByPathList);
|
||||
}
|
||||
return super.postProcessSupportingFileData(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String removeNonNameElementToCamelCase(String name) {
|
||||
return removeNonNameElementToCamelCase(name, "[-:;#]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove " to avoid code injection
|
||||
return input.replace("\"", "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,865 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
* Copyright 2018 SmartBear Software
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.NumberSchema;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.meta.GeneratorMetadata;
|
||||
import org.openapitools.codegen.meta.Stability;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import static org.openapitools.codegen.utils.StringUtils.camelize;
|
||||
import static org.openapitools.codegen.utils.StringUtils.underscore;
|
||||
|
||||
|
||||
public class TypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TypeScriptClientCodegen.class);
|
||||
|
||||
private static final String X_DISCRIMINATOR_TYPE = "x-discriminator-value";
|
||||
private static final String UNDEFINED_VALUE = "undefined";
|
||||
|
||||
private static final String FRAMEWORK_SWITCH = "framework";
|
||||
private static final String FRAMEWORK_SWITCH_DESC = "Specify the framework which should be used in the client code.";
|
||||
private static final String[] FRAMEWORKS = { "fetch-api", "jquery" };
|
||||
private static final String PLATFORM_SWITCH = "platform";
|
||||
private static final String PLATFORM_SWITCH_DESC = "Specifies the platform the code should run on. The default is 'node' for the 'request' framework and 'browser' otherwise.";
|
||||
private static final String[] PLATFORMS = { "browser", "node" };
|
||||
private static final String FILE_CONTENT_DATA_TYPE= "fileContentDataType";
|
||||
private static final String FILE_CONTENT_DATA_TYPE_DESC = "Specifies the type to use for the content of a file - i.e. Blob (Browser) / Buffer (node)";
|
||||
private static final String USE_RXJS_SWITCH = "useRxJS";
|
||||
private static final String USE_RXJS_SWITCH_DESC = "Enable this to internally use rxjs observables. If disabled, a stub is used instead. This is required for the 'angular' framework.";
|
||||
|
||||
private final Map<String, String> frameworkToHttpLibMap;
|
||||
|
||||
// NPM Options
|
||||
private static final String SNAPSHOT = "snapshot";
|
||||
@SuppressWarnings("squid:S5164")
|
||||
protected static final ThreadLocal<SimpleDateFormat> SNAPSHOT_SUFFIX_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMddHHmm", Locale.ROOT));
|
||||
private static final String NPM_REPOSITORY = "npmRepository";
|
||||
private static final String NPM_NAME = "npmName";
|
||||
private static final String NPM_VERSION = "npmVersion";
|
||||
|
||||
// NPM Option Values
|
||||
protected String npmRepository = null;
|
||||
protected String snapshot = null;
|
||||
protected String npmName = null;
|
||||
protected String npmVersion = "1.0.0";
|
||||
protected String modelPropertyNaming = "camelCase";
|
||||
protected HashSet<String> languageGenericTypes;
|
||||
|
||||
public TypeScriptClientCodegen() {
|
||||
super();
|
||||
|
||||
this.frameworkToHttpLibMap = new HashMap<>();
|
||||
this.frameworkToHttpLibMap.put("fetch-api", "isomorphic-fetch");
|
||||
this.frameworkToHttpLibMap.put("jquery", "jquery");
|
||||
|
||||
|
||||
this.generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata).stability(Stability.EXPERIMENTAL).build();
|
||||
|
||||
// clear import mapping (from default generator) as TS does not use it
|
||||
// at the moment
|
||||
importMapping.clear();
|
||||
outputFolder = "generated-code" + File.separator + "typescript";
|
||||
embeddedTemplateDir = templateDir = "typescript";
|
||||
|
||||
supportsInheritance = true;
|
||||
|
||||
// NOTE: TypeScript uses camel cased reserved words, while models are title cased. We don't want lowercase comparisons.
|
||||
reservedWords.addAll(Arrays.asList(
|
||||
// local variable names used in API methods (endpoints)
|
||||
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
|
||||
"requestOptions",
|
||||
// Typescript reserved words
|
||||
"abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with", "yield"));
|
||||
|
||||
languageSpecificPrimitives = new HashSet<>(Arrays.asList(
|
||||
"string",
|
||||
"String",
|
||||
"boolean",
|
||||
"Boolean",
|
||||
"Double",
|
||||
"Integer",
|
||||
"Long",
|
||||
"Float",
|
||||
"Object",
|
||||
"Array",
|
||||
"Date",
|
||||
"number",
|
||||
"any",
|
||||
"File",
|
||||
"Error",
|
||||
"Map"
|
||||
));
|
||||
|
||||
languageGenericTypes = new HashSet<String>(Arrays.asList(
|
||||
"Array"
|
||||
));
|
||||
|
||||
instantiationTypes.put("array", "Array");
|
||||
|
||||
typeMapping = new HashMap<String, String>();
|
||||
typeMapping.put("Array", "Array");
|
||||
typeMapping.put("array", "Array");
|
||||
typeMapping.put("List", "Array");
|
||||
typeMapping.put("boolean", "boolean");
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("int", "number");
|
||||
typeMapping.put("float", "number");
|
||||
typeMapping.put("number", "number");
|
||||
typeMapping.put("long", "number");
|
||||
typeMapping.put("short", "number");
|
||||
typeMapping.put("char", "string");
|
||||
typeMapping.put("double", "number");
|
||||
typeMapping.put("object", "any");
|
||||
typeMapping.put("integer", "number");
|
||||
typeMapping.put("Map", "any");
|
||||
typeMapping.put("date", "string");
|
||||
typeMapping.put("DateTime", "Date");
|
||||
typeMapping.put("binary", "any");
|
||||
// TODO: allow other types for file e.g. Blob
|
||||
typeMapping.put("File", "any");
|
||||
typeMapping.put("ByteArray", "string");
|
||||
typeMapping.put("UUID", "string");
|
||||
typeMapping.put("Error", "Error");
|
||||
|
||||
|
||||
cliOptions.add(new CliOption(NPM_NAME, "The name under which you want to publish generated npm package." +
|
||||
" Required to generate a full package"));
|
||||
cliOptions.add(new CliOption(NPM_VERSION, "The version of your npm package. If not provided, using the version from the OpenAPI specification file.").defaultValue(this.getNpmVersion()));
|
||||
cliOptions.add(new CliOption(NPM_REPOSITORY, "Use this property to set an url your private npmRepo in the package.json"));
|
||||
cliOptions.add(CliOption.newBoolean(SNAPSHOT,
|
||||
"When setting this property to true, the version will be suffixed with -SNAPSHOT." + this.SNAPSHOT_SUFFIX_FORMAT.get().toPattern(),
|
||||
false));
|
||||
|
||||
cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase"));
|
||||
cliOptions.add(new CliOption(CodegenConstants.SUPPORTS_ES6, CodegenConstants.SUPPORTS_ES6_DESC).defaultValue("false"));
|
||||
cliOptions.add(new CliOption(TypeScriptClientCodegen.FILE_CONTENT_DATA_TYPE, TypeScriptClientCodegen.FILE_CONTENT_DATA_TYPE_DESC).defaultValue("Buffer"));
|
||||
cliOptions.add(new CliOption(TypeScriptClientCodegen.USE_RXJS_SWITCH, TypeScriptClientCodegen.USE_RXJS_SWITCH_DESC).defaultValue("false"));
|
||||
|
||||
CliOption frameworkOption = new CliOption(TypeScriptClientCodegen.FRAMEWORK_SWITCH, TypeScriptClientCodegen.FRAMEWORK_SWITCH_DESC);
|
||||
for (String option: TypeScriptClientCodegen.FRAMEWORKS) {
|
||||
// TODO: improve description?
|
||||
frameworkOption.addEnum(option, option);
|
||||
}
|
||||
frameworkOption.defaultValue(FRAMEWORKS[0]);
|
||||
cliOptions.add(frameworkOption);
|
||||
|
||||
CliOption platformOption = new CliOption(TypeScriptClientCodegen.PLATFORM_SWITCH, TypeScriptClientCodegen.PLATFORM_SWITCH_DESC);
|
||||
for (String option: TypeScriptClientCodegen.PLATFORMS) {
|
||||
// TODO: improve description?
|
||||
platformOption.addEnum(option, option);
|
||||
}
|
||||
platformOption.defaultValue(PLATFORMS[0]);
|
||||
|
||||
cliOptions.add(platformOption);
|
||||
|
||||
|
||||
// TODO: gen package.json?
|
||||
|
||||
//Documentation
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
|
||||
supportingFiles.add(new SupportingFile("tsconfig.mustache", "", "tsconfig.json"));
|
||||
supportingFiles.add(new SupportingFile(".gitignore.mustache", "", ".gitignore"));
|
||||
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
|
||||
|
||||
// Util
|
||||
supportingFiles.add(new SupportingFile("util.mustache", "", "util.ts"));
|
||||
supportingFiles.add(new SupportingFile("api" + File.separator + "exception.mustache", "apis", "exception.ts"));
|
||||
// http
|
||||
supportingFiles.add(new SupportingFile("http" + File.separator + "http.mustache", "http", "http.ts"));
|
||||
supportingFiles.add(new SupportingFile("http" + File.separator + "servers.mustache", "servers.ts"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("configuration.mustache", "", "configuration.ts"));
|
||||
supportingFiles.add(new SupportingFile("auth" + File.separator + "auth.mustache", "auth", "auth.ts"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("model" + File.separator + "models_all.mustache", "models", "all.ts"));
|
||||
|
||||
// TODO: add supporting files depending on cli parameter e.g. fetch vs angular
|
||||
supportingFiles.add(new SupportingFile("types" + File.separator + "PromiseAPI.mustache", "types", "PromiseAPI.ts"));
|
||||
supportingFiles.add(new SupportingFile("types" + File.separator + "ObservableAPI.mustache", "types", "ObservableAPI.ts"));
|
||||
|
||||
// models
|
||||
// TODO: properly set model and api packages
|
||||
this.setModelPackage("");
|
||||
supportingFiles.add(new SupportingFile("model" + File.separator + "ObjectSerializer.mustache", "models", "ObjectSerializer.ts"));
|
||||
modelTemplateFiles.put("model" + File.separator + "model.mustache", ".ts");
|
||||
|
||||
// api
|
||||
this.setApiPackage("");
|
||||
supportingFiles.add(new SupportingFile("api" + File.separator + "middleware.mustache", "", "middleware.ts"));
|
||||
this.supportingFiles.add(new SupportingFile("api" + File.separator + "baseapi.mustache", "apis", "baseapi.ts"));
|
||||
this.apiTemplateFiles.put("api" + File.separator + "api.mustache", ".ts");
|
||||
}
|
||||
|
||||
public String getNpmName() {
|
||||
return npmName;
|
||||
}
|
||||
|
||||
public void setNpmName(String npmName) {
|
||||
this.npmName = npmName;
|
||||
}
|
||||
|
||||
public String getNpmRepository() {
|
||||
return npmRepository;
|
||||
}
|
||||
|
||||
public void setNpmRepository(String npmRepository) {
|
||||
this.npmRepository = npmRepository;
|
||||
}
|
||||
|
||||
public String getNpmVersion() {
|
||||
return npmVersion;
|
||||
}
|
||||
|
||||
public void setNpmVersion(String npmVersion) {
|
||||
this.npmVersion = npmVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocessOpenAPI(OpenAPI openAPI) {
|
||||
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
|
||||
// If no npmVersion is provided in additional properties, version from API specification is used.
|
||||
// If none of them is provided then fallbacks to default version
|
||||
if (additionalProperties.containsKey(NPM_VERSION)) {
|
||||
this.setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
|
||||
} else if (openAPI.getInfo() != null && openAPI.getInfo().getVersion() != null) {
|
||||
this.setNpmVersion(openAPI.getInfo().getVersion());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(SNAPSHOT) && Boolean.parseBoolean(additionalProperties.get(SNAPSHOT).toString())) {
|
||||
if (npmVersion.toUpperCase(Locale.ROOT).matches("^.*-SNAPSHOT$")) {
|
||||
this.setNpmVersion(npmVersion + "." + SNAPSHOT_SUFFIX_FORMAT.get().format(new Date()));
|
||||
} else {
|
||||
this.setNpmVersion(npmVersion + "-SNAPSHOT." + SNAPSHOT_SUFFIX_FORMAT.get().format(new Date()));
|
||||
}
|
||||
}
|
||||
additionalProperties.put(NPM_VERSION, npmVersion);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
|
||||
final Object propFramework = additionalProperties.get(FRAMEWORK_SWITCH);
|
||||
|
||||
Map<String, Boolean> frameworks = new HashMap<>();
|
||||
for (String framework: FRAMEWORKS) {
|
||||
frameworks.put(framework, framework.equals(propFramework));
|
||||
}
|
||||
objs.put("framework", propFramework);
|
||||
objs.put("frameworks", frameworks);
|
||||
|
||||
objs.put("fileContentDataType", additionalProperties.get(FILE_CONTENT_DATA_TYPE));
|
||||
|
||||
return objs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> operations, List<Object> models) {
|
||||
|
||||
// Add additional filename information for model imports in the apis
|
||||
List<Map<String, Object>> imports = (List<Map<String, Object>>) operations.get("imports");
|
||||
for (Map<String, Object> im : imports) {
|
||||
im.put("filename", ((String) im.get("import")).replace(".", File.separator));
|
||||
im.put("classname", getModelnameFromModelFilename(im.get("import").toString()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> operationsMap = (Map<String, Object>) operations.get("operations");
|
||||
List<CodegenOperation> operationList = (List<CodegenOperation>) operationsMap.get("operation");
|
||||
for (CodegenOperation operation: operationList) {
|
||||
List<CodegenResponse> responses = operation.responses;
|
||||
operation.returnType = this.getReturnType(responses);
|
||||
}
|
||||
return operations;
|
||||
}
|
||||
|
||||
private String getReturnType(List<CodegenResponse> responses) {
|
||||
StringBuilder returnType = new StringBuilder();
|
||||
boolean firstReturnType = true;
|
||||
boolean atLeastOneSuccess = false;
|
||||
boolean addVoid = false;
|
||||
for (CodegenResponse response: responses) {
|
||||
// TODO: we should probably catch an exception here
|
||||
if (response.is2xx) {
|
||||
if (response.dataType != null) {
|
||||
if (!firstReturnType) {
|
||||
returnType.append(" | ");
|
||||
}
|
||||
returnType.append(response.dataType);
|
||||
firstReturnType = false;
|
||||
atLeastOneSuccess = true;
|
||||
} else {
|
||||
addVoid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!atLeastOneSuccess) {
|
||||
return null;
|
||||
} else if (addVoid) {
|
||||
returnType.append(" | void");
|
||||
}
|
||||
|
||||
return returnType.toString();
|
||||
}
|
||||
|
||||
private String getModelnameFromModelFilename(String filename) {
|
||||
String name = filename.substring((modelPackage() + File.separator).length());
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeReservedWord(String name) {
|
||||
if (this.reservedWordsMappings().containsKey(name)) {
|
||||
return this.reservedWordsMappings().get(name);
|
||||
}
|
||||
return "_" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
// should be the same as variable name
|
||||
return toVarName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toVarName(String name) {
|
||||
// sanitize name
|
||||
name = sanitizeName(name);
|
||||
|
||||
if ("_".equals(name)) {
|
||||
name = "_u";
|
||||
}
|
||||
|
||||
// if it's all uppper case, do nothing
|
||||
if (name.matches("^[A-Z_]*$")) {
|
||||
return name;
|
||||
}
|
||||
|
||||
name = getNameUsingModelPropertyNaming(name);
|
||||
|
||||
// for reserved word or word starting with number, append _
|
||||
if (isReservedWord(name) || name.matches("^\\d.*")) {
|
||||
name = escapeReservedWord(name);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(String name) {
|
||||
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
||||
|
||||
if (!StringUtils.isEmpty(modelNamePrefix)) {
|
||||
name = modelNamePrefix + "_" + name;
|
||||
}
|
||||
|
||||
if (!StringUtils.isEmpty(modelNameSuffix)) {
|
||||
name = name + "_" + modelNameSuffix;
|
||||
}
|
||||
|
||||
// model name cannot use reserved keyword, e.g. return
|
||||
if (isReservedWord(name)) {
|
||||
String modelName = camelize("model_" + name);
|
||||
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
|
||||
return modelName;
|
||||
}
|
||||
|
||||
// model name starts with number
|
||||
if (name.matches("^\\d.*")) {
|
||||
String modelName = camelize("model_" + name); // e.g. 200Response => Model200Response (after camelize)
|
||||
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
|
||||
return modelName;
|
||||
}
|
||||
|
||||
if (languageSpecificPrimitives.contains(name)) {
|
||||
String modelName = camelize("model_" + name);
|
||||
LOGGER.warn(name + " (model name matches existing language type) cannot be used as a model name. Renamed to " + modelName);
|
||||
return modelName;
|
||||
}
|
||||
|
||||
// camelize the model name
|
||||
// phone_number => PhoneNumber
|
||||
return camelize(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
// should be the same as the model name
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getParameterDataType(Parameter parameter, Schema p) {
|
||||
// handle enums of various data types
|
||||
Schema inner;
|
||||
if (ModelUtils.isArraySchema(p)) {
|
||||
ArraySchema mp1 = (ArraySchema) p;
|
||||
inner = mp1.getItems();
|
||||
return this.getSchemaType(p) + "<" + this.getParameterDataType(parameter, inner) + ">";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
inner = (Schema) p.getAdditionalProperties();
|
||||
return "{ [key: string]: " + this.getParameterDataType(parameter, inner) + "; }";
|
||||
} else if (ModelUtils.isStringSchema(p)) {
|
||||
// Handle string enums
|
||||
if (p.getEnum() != null) {
|
||||
return enumValuesToEnumTypeUnion(p.getEnum(), "string");
|
||||
}
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
// Handle integer enums
|
||||
if (p.getEnum() != null) {
|
||||
return numericEnumValuesToEnumTypeUnion(new ArrayList<Number>(p.getEnum()));
|
||||
}
|
||||
} else if (ModelUtils.isNumberSchema(p)) {
|
||||
// Handle double enums
|
||||
if (p.getEnum() != null) {
|
||||
return numericEnumValuesToEnumTypeUnion(new ArrayList<Number>(p.getEnum()));
|
||||
}
|
||||
}
|
||||
/* TODO revise the logic below
|
||||
else if (ModelUtils.isDateSchema(p)) {
|
||||
// Handle date enums
|
||||
DateSchema sp = (DateSchema) p;
|
||||
if (sp.getEnum() != null) {
|
||||
return enumValuesToEnumTypeUnion(sp.getEnum(), "string");
|
||||
}
|
||||
} else if (ModelUtils.isDateTimeSchema(p)) {
|
||||
// Handle datetime enums
|
||||
DateTimeSchema sp = (DateTimeSchema) p;
|
||||
if (sp.getEnum() != null) {
|
||||
return enumValuesToEnumTypeUnion(sp.getEnum(), "string");
|
||||
}
|
||||
}*/
|
||||
return this.getTypeDeclaration(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of strings to a literal union for representing enum values as a type.
|
||||
* Example output: 'available' | 'pending' | 'sold'
|
||||
*
|
||||
* @param values list of allowed enum values
|
||||
* @param dataType either "string" or "number"
|
||||
* @return a literal union for representing enum values as a type
|
||||
*/
|
||||
protected String enumValuesToEnumTypeUnion(List<String> values, String dataType) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
boolean isFirst = true;
|
||||
for (String value : values) {
|
||||
if (!isFirst) {
|
||||
b.append(" | ");
|
||||
}
|
||||
b.append(toEnumValue(value.toString(), dataType));
|
||||
isFirst = false;
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of numbers to a literal union for representing enum values as a type.
|
||||
* Example output: 3 | 9 | 55
|
||||
*
|
||||
* @param values a list of numbers
|
||||
* @return a literal union for representing enum values as a type
|
||||
*/
|
||||
protected String numericEnumValuesToEnumTypeUnion(List<Number> values) {
|
||||
List<String> stringValues = new ArrayList<>();
|
||||
for (Number value : values) {
|
||||
stringValues.add(value.toString());
|
||||
}
|
||||
return enumValuesToEnumTypeUnion(stringValues, "number");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDefaultValue(Schema p) {
|
||||
if (ModelUtils.isBooleanSchema(p)) {
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (ModelUtils.isDateSchema(p)) {
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (ModelUtils.isDateTimeSchema(p)) {
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (ModelUtils.isNumberSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
}
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (ModelUtils.isIntegerSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return p.getDefault().toString();
|
||||
}
|
||||
return UNDEFINED_VALUE;
|
||||
} else if (ModelUtils.isStringSchema(p)) {
|
||||
if (p.getDefault() != null) {
|
||||
return "'" + (String) p.getDefault() + "'";
|
||||
}
|
||||
return UNDEFINED_VALUE;
|
||||
} else {
|
||||
return UNDEFINED_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isReservedWord(String word) {
|
||||
// NOTE: This differs from super's implementation in that TypeScript does _not_ want case insensitive matching.
|
||||
return reservedWords.contains(word);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (languageSpecificPrimitives.contains(type))
|
||||
return type;
|
||||
} else
|
||||
type = openAPIType;
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toOperationId(String operationId) {
|
||||
// throw exception if method name is empty
|
||||
if (StringUtils.isEmpty(operationId)) {
|
||||
throw new RuntimeException("Empty method name (operationId) not allowed");
|
||||
}
|
||||
|
||||
// method name cannot use reserved keyword, e.g. return
|
||||
// append _ at the beginning, e.g. _return
|
||||
if (isReservedWord(operationId)) {
|
||||
return escapeReservedWord(camelize(sanitizeName(operationId), true));
|
||||
}
|
||||
|
||||
return camelize(sanitizeName(operationId), true);
|
||||
}
|
||||
|
||||
public void setModelPropertyNaming(String naming) {
|
||||
if ("original".equals(naming) || "camelCase".equals(naming) ||
|
||||
"PascalCase".equals(naming) || "snake_case".equals(naming)) {
|
||||
this.modelPropertyNaming = naming;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid model property naming '" +
|
||||
naming + "'. Must be 'original', 'camelCase', " +
|
||||
"'PascalCase' or 'snake_case'");
|
||||
}
|
||||
}
|
||||
|
||||
public String getModelPropertyNaming() {
|
||||
return this.modelPropertyNaming;
|
||||
}
|
||||
|
||||
public String getNameUsingModelPropertyNaming(String name) {
|
||||
switch (CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.valueOf(getModelPropertyNaming())) {
|
||||
case original:
|
||||
return name;
|
||||
case camelCase:
|
||||
return camelize(name, true);
|
||||
case PascalCase:
|
||||
return camelize(name);
|
||||
case snake_case:
|
||||
return underscore(name);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid model property naming '" +
|
||||
name + "'. Must be 'original', 'camelCase', " +
|
||||
"'PascalCase' or 'snake_case'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumValue(String value, String datatype) {
|
||||
if ("number".equals(datatype)) {
|
||||
return value;
|
||||
} else {
|
||||
return "\'" + escapeText(value) + "\'";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumDefaultValue(String value, String datatype) {
|
||||
return datatype + "_" + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumVarName(String name, String datatype) {
|
||||
if (name.length() == 0) {
|
||||
return "Empty";
|
||||
}
|
||||
|
||||
// for symbol, e.g. $, #
|
||||
if (getSymbolName(name) != null) {
|
||||
return camelize(getSymbolName(name));
|
||||
}
|
||||
|
||||
// number
|
||||
if ("number".equals(datatype)) {
|
||||
String varName = "NUMBER_" + name;
|
||||
|
||||
varName = varName.replaceAll("-", "MINUS_");
|
||||
varName = varName.replaceAll("\\+", "PLUS_");
|
||||
varName = varName.replaceAll("\\.", "_DOT_");
|
||||
return varName;
|
||||
}
|
||||
|
||||
// string
|
||||
String enumName = sanitizeName(name);
|
||||
enumName = enumName.replaceFirst("^_", "");
|
||||
enumName = enumName.replaceFirst("_$", "");
|
||||
|
||||
// camelize the enum variable name
|
||||
// ref: https://basarat.gitbooks.io/typescript/content/docs/enums.html
|
||||
enumName = camelize(enumName);
|
||||
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return "_" + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEnumName(CodegenProperty property) {
|
||||
String enumName = toModelName(property.name) + "Enum";
|
||||
|
||||
if (enumName.matches("\\d.*")) { // starts with number
|
||||
return "_" + enumName;
|
||||
} else {
|
||||
return enumName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||
// process enum in models
|
||||
List<Map<String, Object>> models = (List<Map<String, Object>>) postProcessModelsEnum(objs).get("models");
|
||||
for (Object _mo : models) {
|
||||
Map<String, Object> mo = (Map<String, Object>) _mo;
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
cm.imports = new TreeSet(cm.imports);
|
||||
// name enum with model name, e.g. StatusEnum => Pet.StatusEnum
|
||||
for (CodegenProperty var : cm.vars) {
|
||||
if (Boolean.TRUE.equals(var.isEnum)) {
|
||||
var.datatypeWithEnum = var.datatypeWithEnum.replace(var.enumName, cm.classname + var.enumName);
|
||||
}
|
||||
}
|
||||
if (cm.parent != null) {
|
||||
for (CodegenProperty var : cm.allVars) {
|
||||
if (Boolean.TRUE.equals(var.isEnum)) {
|
||||
var.datatypeWithEnum = var.datatypeWithEnum
|
||||
.replace(var.enumName, cm.classname + var.enumName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map<String, Object> mo : models) {
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
// Add additional filename information for imports
|
||||
mo.put("tsImports", toTsImports(cm, cm.imports));
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
private List<Map<String, String>> toTsImports(CodegenModel cm, Set<String> imports) {
|
||||
List<Map<String, String>> tsImports = new ArrayList<>();
|
||||
for (String im : imports) {
|
||||
if (!im.equals(cm.classname)) {
|
||||
HashMap<String, String> tsImport = new HashMap<>();
|
||||
// TVG: This is used as class name in the import statements of the model file
|
||||
tsImport.put("classname", im);
|
||||
tsImport.put("filename", toModelFilename(im));
|
||||
tsImports.add(tsImport);
|
||||
}
|
||||
}
|
||||
return tsImports;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
|
||||
Map<String, Object> result = super.postProcessAllModels(objs);
|
||||
|
||||
for (Map.Entry<String, Object> entry : result.entrySet()) {
|
||||
Map<String, Object> inner = (Map<String, Object>) entry.getValue();
|
||||
List<Map<String, Object>> models = (List<Map<String, Object>>) inner.get("models");
|
||||
for (Map<String, Object> mo : models) {
|
||||
CodegenModel cm = (CodegenModel) mo.get("model");
|
||||
if (cm.discriminator != null && cm.children != null) {
|
||||
for (CodegenModel child : cm.children) {
|
||||
this.setDiscriminatorValue(child, cm.discriminator.getPropertyName(), this.getDiscriminatorValue(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void setDiscriminatorValue(CodegenModel model, String baseName, String value) {
|
||||
for (CodegenProperty prop : model.allVars) {
|
||||
if (prop.baseName.equals(baseName)) {
|
||||
prop.discriminatorValue = value;
|
||||
}
|
||||
}
|
||||
if (model.children != null) {
|
||||
final boolean newDiscriminator = model.discriminator != null;
|
||||
for (CodegenModel child : model.children) {
|
||||
this.setDiscriminatorValue(child, baseName, newDiscriminator ? value : this.getDiscriminatorValue(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getDiscriminatorValue(CodegenModel model) {
|
||||
return model.vendorExtensions.containsKey(X_DISCRIMINATOR_TYPE) ?
|
||||
(String) model.vendorExtensions.get(X_DISCRIMINATOR_TYPE) : model.classname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove ', " to avoid code injection
|
||||
return input.replace("\"", "").replace("'", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "typescript";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates a TypeScript client library using Fetch API (beta).";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
|
||||
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
|
||||
}
|
||||
|
||||
convertPropertyToBooleanAndWriteBack(CodegenConstants.SUPPORTS_ES6);
|
||||
|
||||
// change package names
|
||||
apiPackage = this.apiPackage + ".apis";
|
||||
modelPackage = this.modelPackage + ".models";
|
||||
testPackage = this.testPackage + ".tests";
|
||||
|
||||
additionalProperties.putIfAbsent(FRAMEWORK_SWITCH, FRAMEWORKS[0]);
|
||||
supportingFiles.add(new SupportingFile("index.mustache", "index.ts"));
|
||||
|
||||
String httpLibName = this.getHttpLibForFramework(additionalProperties.get(FRAMEWORK_SWITCH).toString());
|
||||
supportingFiles.add(new SupportingFile(
|
||||
"http" + File.separator + httpLibName + ".mustache",
|
||||
"http", httpLibName + ".ts"
|
||||
));
|
||||
|
||||
Object propPlatform = additionalProperties.get(PLATFORM_SWITCH);
|
||||
if (propPlatform == null) {
|
||||
propPlatform = "browser";
|
||||
additionalProperties.put("platform", propPlatform);
|
||||
}
|
||||
|
||||
Map<String, Boolean> platforms = new HashMap<>();
|
||||
for (String platform: PLATFORMS) {
|
||||
platforms.put(platform, platform.equals(propPlatform));
|
||||
}
|
||||
additionalProperties.put("platforms", platforms);
|
||||
|
||||
additionalProperties.putIfAbsent(FILE_CONTENT_DATA_TYPE, propPlatform.equals("node") ? "Buffer" : "Blob");
|
||||
|
||||
final boolean useRxJS = convertPropertyToBooleanAndWriteBack(USE_RXJS_SWITCH);
|
||||
if (!useRxJS) {
|
||||
supportingFiles.add(new SupportingFile("rxjsStub.mustache", "rxjsStub.ts"));
|
||||
}
|
||||
|
||||
// NPM Settings
|
||||
if (additionalProperties.containsKey(NPM_NAME)) {
|
||||
setNpmName(additionalProperties.get(NPM_NAME).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(NPM_VERSION)) {
|
||||
setNpmVersion(additionalProperties.get(NPM_VERSION).toString());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(NPM_REPOSITORY)) {
|
||||
setNpmRepository(additionalProperties.get(NPM_REPOSITORY).toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private String getHttpLibForFramework(String object) {
|
||||
return this.frameworkToHttpLibMap.get(object);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getTypeDeclaration(Schema p) {
|
||||
Schema inner;
|
||||
if (ModelUtils.isArraySchema(p)) {
|
||||
inner = ((ArraySchema) p).getItems();
|
||||
return this.getSchemaType(p) + "<" + this.getTypeDeclaration(inner) + ">";
|
||||
} else if (ModelUtils.isMapSchema(p)) {
|
||||
inner = (Schema) p.getAdditionalProperties();
|
||||
return "{ [key: string]: " + this.getTypeDeclaration(inner) + "; }";
|
||||
} else if (ModelUtils.isFileSchema(p)) {
|
||||
// TODO: Change type declaration
|
||||
return "HttpFile";
|
||||
} else if (ModelUtils.isBinarySchema(p)) {
|
||||
return "any";
|
||||
} else {
|
||||
return super.getTypeDeclaration(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) {
|
||||
codegenModel.additionalPropertiesType = getTypeDeclaration((Schema) schema.getAdditionalProperties());
|
||||
addImport(codegenModel, codegenModel.additionalPropertiesType);
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public class ProcessUtils {
|
||||
public static boolean hasHttpBearerMethods(List<CodegenSecurity> authMethods) {
|
||||
if (authMethods != null && !authMethods.isEmpty()) {
|
||||
for (CodegenSecurity cs : authMethods) {
|
||||
if (Boolean.TRUE.equals(cs.isBasicBearer)) {
|
||||
if (Boolean.TRUE.equals(cs.isBasicBasic)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,15 +53,9 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.text.DateFormat;
|
||||
|
||||
import {{invokerPackage}}.auth.Authentication;
|
||||
{{#hasHttpBasicMethods}}
|
||||
import {{invokerPackage}}.auth.HttpBasicAuth;
|
||||
{{/hasHttpBasicMethods}}
|
||||
{{#hasHttpBearerMethods}}
|
||||
import {{invokerPackage}}.auth.HttpBearerAuth;
|
||||
{{/hasHttpBearerMethods}}
|
||||
{{#hasApiKeyMethods}}
|
||||
import {{invokerPackage}}.auth.ApiKeyAuth;
|
||||
{{/hasApiKeyMethods}}
|
||||
{{#hasOAuthMethods}}
|
||||
import {{invokerPackage}}.auth.OAuth;
|
||||
{{/hasOAuthMethods}}
|
||||
@@ -273,24 +267,6 @@ public class ApiClient {
|
||||
return authentications.get(authName);
|
||||
}
|
||||
|
||||
{{#hasHttpBearerMethods}}
|
||||
/**
|
||||
* Helper method to set access token for the first Bearer authentication.
|
||||
* @param bearerToken Bearer token
|
||||
*/
|
||||
public void setBearerToken(String bearerToken) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof HttpBearerAuth) {
|
||||
((HttpBearerAuth) auth).setBearerToken(bearerToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No Bearer authentication configured!");
|
||||
}
|
||||
|
||||
{{/hasHttpBearerMethods}}
|
||||
|
||||
{{#hasHttpBasicMethods}}
|
||||
/**
|
||||
* Helper method to set username for the first HTTP basic authentication.
|
||||
* @param username Username
|
||||
@@ -319,9 +295,6 @@ public class ApiClient {
|
||||
throw new RuntimeException("No HTTP basic authentication configured!");
|
||||
}
|
||||
|
||||
{{/hasHttpBasicMethods}}
|
||||
|
||||
{{#hasApiKeyMethods}}
|
||||
/**
|
||||
* Helper method to set API key value for the first API key authentication.
|
||||
* @param apiKey the API key
|
||||
@@ -350,8 +323,6 @@ public class ApiClient {
|
||||
throw new RuntimeException("No API key authentication configured!");
|
||||
}
|
||||
|
||||
{{/hasApiKeyMethods}}
|
||||
|
||||
{{#hasOAuthMethods}}
|
||||
/**
|
||||
* Helper method to set access token for the first OAuth2 authentication.
|
||||
@@ -369,6 +340,20 @@ public class ApiClient {
|
||||
|
||||
{{/hasOAuthMethods}}
|
||||
|
||||
/**
|
||||
* Helper method to set access token for the first Bearer authentication.
|
||||
* @param bearerToken Bearer token
|
||||
*/
|
||||
public void setBearerToken(String bearerToken) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof HttpBearerAuth) {
|
||||
((HttpBearerAuth) auth).setBearerToken(bearerToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No Bearer authentication configured!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the User-Agent header's value (by adding to the default header map).
|
||||
* @param userAgent User agent
|
||||
|
||||
@@ -3,13 +3,10 @@
|
||||
package {{invokerPackage}}.model;
|
||||
|
||||
import {{invokerPackage}}.ApiException;
|
||||
import java.util.Objects;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.core.GenericType;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Abstract class for oneOf,anyOf schemas defined in OpenAPI spec
|
||||
*/
|
||||
@@ -42,7 +39,6 @@ public abstract class AbstractOpenApiSchema {
|
||||
*
|
||||
* @return an instance of the actual schema/object
|
||||
*/
|
||||
@JsonValue
|
||||
public Object getActualInstance() {return instance;}
|
||||
|
||||
/***
|
||||
@@ -61,46 +57,6 @@ public abstract class AbstractOpenApiSchema {
|
||||
return schemaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("class ").append(getClass()).append(" {\n");
|
||||
sb.append(" instance: ").append(toIndentedString(instance)).append("\n");
|
||||
sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n");
|
||||
sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n");
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given object to string with each line indented by 4 spaces
|
||||
* (except the first line).
|
||||
*/
|
||||
private String toIndentedString(java.lang.Object o) {
|
||||
if (o == null) {
|
||||
return "null";
|
||||
}
|
||||
return o.toString().replace("\n", "\n ");
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
AbstractOpenApiSchema a = (AbstractOpenApiSchema) o;
|
||||
return Objects.equals(this.instance, a.instance) &&
|
||||
Objects.equals(this.isNullable, a.isNullable) &&
|
||||
Objects.equals(this.schemaType, a.schemaType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(instance, isNullable, schemaType);
|
||||
}
|
||||
|
||||
/***
|
||||
* Is nullalble
|
||||
*
|
||||
|
||||
@@ -59,9 +59,7 @@ import java.util.regex.Pattern;
|
||||
import {{invokerPackage}}.auth.Authentication;
|
||||
import {{invokerPackage}}.auth.HttpBasicAuth;
|
||||
import {{invokerPackage}}.auth.HttpBearerAuth;
|
||||
{{#hasHttpSignatureMethods}}
|
||||
import {{invokerPackage}}.auth.HttpSignatureAuth;
|
||||
{{/hasHttpSignatureMethods}}
|
||||
import {{invokerPackage}}.auth.ApiKeyAuth;
|
||||
{{#hasOAuthMethods}}
|
||||
import {{invokerPackage}}.auth.OAuth;
|
||||
|
||||
@@ -1,51 +1,11 @@
|
||||
import javax.ws.rs.core.GenericType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
|
||||
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}}
|
||||
@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class)
|
||||
public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} {
|
||||
public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> {
|
||||
public {{classname}}Deserializer() {
|
||||
this({{classname}}.class);
|
||||
}
|
||||
|
||||
public {{classname}}Deserializer(Class<?> vc) {
|
||||
super(vc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
||||
JsonNode tree = jp.readValueAsTree();
|
||||
|
||||
int match = 0;
|
||||
Object deserialized = null;
|
||||
{{#oneOf}}
|
||||
try {
|
||||
deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class);
|
||||
match++;
|
||||
} catch (Exception e) {
|
||||
// deserialization failed, continue
|
||||
}
|
||||
{{/oneOf}}
|
||||
if (match == 1) {
|
||||
{{classname}} ret = new {{classname}}();
|
||||
ret.setActualInstance(deserialized);
|
||||
return ret;
|
||||
}
|
||||
throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match));
|
||||
}
|
||||
}
|
||||
|
||||
// store a list of schema names defined in oneOf
|
||||
public final static Map<String, GenericType> schemas = new HashMap<String, GenericType>();
|
||||
@@ -54,13 +14,6 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im
|
||||
super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}});
|
||||
}
|
||||
|
||||
{{#oneOf}}
|
||||
public {{classname}}({{{.}}} o) {
|
||||
super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}});
|
||||
setActualInstance(o);
|
||||
}
|
||||
{{/oneOf}}
|
||||
|
||||
static {
|
||||
{{#oneOf}}
|
||||
schemas.put("{{{.}}}", new GenericType<{{{.}}}>() {
|
||||
|
||||
@@ -338,13 +338,13 @@
|
||||
<version>${commons-io-version}</version>
|
||||
</dependency>
|
||||
{{/supportJava6}}
|
||||
{{#hasHttpSignatureMethods}}
|
||||
{{#hasHttpBasicMethods}}
|
||||
<dependency>
|
||||
<groupId>org.tomitribe</groupId>
|
||||
<artifactId>tomitribe-http-signatures</artifactId>
|
||||
<version>${http-signature-version}</version>
|
||||
</dependency>
|
||||
{{/hasHttpSignatureMethods}}
|
||||
{{/hasHttpBasicMethods}}
|
||||
{{#hasOAuthMethods}}
|
||||
<dependency>
|
||||
<groupId>com.github.scribejava</groupId>
|
||||
@@ -387,9 +387,9 @@
|
||||
<threetenbp-version>2.9.10</threetenbp-version>
|
||||
{{/threetenbp}}
|
||||
<junit-version>4.13</junit-version>
|
||||
{{#hasHttpSignatureMethods}}
|
||||
{{#hasHttpBasicMethods}}
|
||||
<http-signature-version>1.4</http-signature-version>
|
||||
{{/hasHttpSignatureMethods}}
|
||||
{{/hasHttpBasicMethods}}
|
||||
{{#hasOAuthMethods}}
|
||||
<scribejava-apis-version>6.9.0</scribejava-apis-version>
|
||||
{{/hasOAuthMethods}}
|
||||
|
||||
@@ -66,15 +66,9 @@ import java.util.Map.Entry;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import {{invokerPackage}}.auth.Authentication;
|
||||
{{#hasHttpBasicMethods}}
|
||||
import {{invokerPackage}}.auth.HttpBasicAuth;
|
||||
{{/hasHttpBasicMethods}}
|
||||
{{#hasHttpBearerMethods}}
|
||||
import {{invokerPackage}}.auth.HttpBearerAuth;
|
||||
{{/hasHttpBearerMethods}}
|
||||
{{#hasApiKeyMethods}}
|
||||
import {{invokerPackage}}.auth.ApiKeyAuth;
|
||||
{{/hasApiKeyMethods}}
|
||||
{{#hasOAuthMethods}}
|
||||
import {{invokerPackage}}.auth.OAuth;
|
||||
{{/hasOAuthMethods}}
|
||||
@@ -176,103 +170,93 @@ public class ApiClient {
|
||||
return authentications.get(authName);
|
||||
}
|
||||
|
||||
{{#hasHttpBearerMethods}}
|
||||
/**
|
||||
* Helper method to set token for HTTP bearer authentication.
|
||||
* @param bearerToken the token
|
||||
*/
|
||||
public void setBearerToken(String bearerToken) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof HttpBearerAuth) {
|
||||
((HttpBearerAuth) auth).setBearerToken(bearerToken);
|
||||
return;
|
||||
/**
|
||||
* Helper method to set token for HTTP bearer authentication.
|
||||
* @param bearerToken the token
|
||||
*/
|
||||
public void setBearerToken(String bearerToken) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof HttpBearerAuth) {
|
||||
((HttpBearerAuth) auth).setBearerToken(bearerToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No Bearer authentication configured!");
|
||||
}
|
||||
throw new RuntimeException("No Bearer authentication configured!");
|
||||
}
|
||||
|
||||
{{/hasHttpBearerMethods}}
|
||||
|
||||
{{#hasHttpBasicMethods}}
|
||||
/**
|
||||
* Helper method to set username for the first HTTP basic authentication.
|
||||
* @param username Username
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof HttpBasicAuth) {
|
||||
((HttpBasicAuth) auth).setUsername(username);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Helper method to set username for the first HTTP basic authentication.
|
||||
* @param username the username
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof HttpBasicAuth) {
|
||||
((HttpBasicAuth) auth).setUsername(username);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No HTTP basic authentication configured!");
|
||||
}
|
||||
throw new RuntimeException("No HTTP basic authentication configured!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set password for the first HTTP basic authentication.
|
||||
* @param password Password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof HttpBasicAuth) {
|
||||
((HttpBasicAuth) auth).setPassword(password);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Helper method to set password for the first HTTP basic authentication.
|
||||
* @param password the password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof HttpBasicAuth) {
|
||||
((HttpBasicAuth) auth).setPassword(password);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No HTTP basic authentication configured!");
|
||||
}
|
||||
throw new RuntimeException("No HTTP basic authentication configured!");
|
||||
}
|
||||
|
||||
{{/hasHttpBasicMethods}}
|
||||
|
||||
{{#hasApiKeyMethods}}
|
||||
/**
|
||||
* Helper method to set API key value for the first API key authentication.
|
||||
* @param apiKey the API key
|
||||
*/
|
||||
public void setApiKey(String apiKey) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof ApiKeyAuth) {
|
||||
((ApiKeyAuth) auth).setApiKey(apiKey);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Helper method to set API key value for the first API key authentication.
|
||||
* @param apiKey the API key
|
||||
*/
|
||||
public void setApiKey(String apiKey) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof ApiKeyAuth) {
|
||||
((ApiKeyAuth) auth).setApiKey(apiKey);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No API key authentication configured!");
|
||||
}
|
||||
throw new RuntimeException("No API key authentication configured!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set API key prefix for the first API key authentication.
|
||||
* @param apiKeyPrefix API key prefix
|
||||
*/
|
||||
public void setApiKeyPrefix(String apiKeyPrefix) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof ApiKeyAuth) {
|
||||
((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Helper method to set API key prefix for the first API key authentication.
|
||||
* @param apiKeyPrefix the API key prefix
|
||||
*/
|
||||
public void setApiKeyPrefix(String apiKeyPrefix) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof ApiKeyAuth) {
|
||||
((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No API key authentication configured!");
|
||||
}
|
||||
throw new RuntimeException("No API key authentication configured!");
|
||||
}
|
||||
|
||||
{{/hasApiKeyMethods}}
|
||||
|
||||
{{#hasOAuthMethods}}
|
||||
/**
|
||||
* Helper method to set access token for the first OAuth2 authentication.
|
||||
* @param accessToken Access token
|
||||
*/
|
||||
public void setAccessToken(String accessToken) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof OAuth) {
|
||||
((OAuth) auth).setAccessToken(accessToken);
|
||||
return;
|
||||
}
|
||||
{{#hasOAuthMethods}}
|
||||
/**
|
||||
* Helper method to set access token for the first OAuth2 authentication.
|
||||
* @param accessToken the access token
|
||||
*/
|
||||
public void setAccessToken(String accessToken) {
|
||||
for (Authentication auth : authentications.values()) {
|
||||
if (auth instanceof OAuth) {
|
||||
((OAuth) auth).setAccessToken(accessToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No OAuth2 authentication configured!");
|
||||
}
|
||||
throw new RuntimeException("No OAuth2 authentication configured!");
|
||||
}
|
||||
|
||||
{{/hasOAuthMethods}}
|
||||
|
||||
/**
|
||||
{{/hasOAuthMethods}}
|
||||
/**
|
||||
* Set the User-Agent header's value (by adding to the default header map).
|
||||
* @param userAgent the user agent string
|
||||
* @return ApiClient this client
|
||||
|
||||
@@ -16,7 +16,6 @@ org.openapitools.codegen.languages.CppPistacheServerCodegen
|
||||
org.openapitools.codegen.languages.CppRestbedServerCodegen
|
||||
org.openapitools.codegen.languages.CppRestSdkClientCodegen
|
||||
org.openapitools.codegen.languages.CppTizenClientCodegen
|
||||
org.openapitools.codegen.languages.CppUE4ClientCodegen
|
||||
org.openapitools.codegen.languages.CSharpClientCodegen
|
||||
org.openapitools.codegen.languages.CSharpNetCoreClientCodegen
|
||||
org.openapitools.codegen.languages.CSharpDotNet2ClientCodegen
|
||||
@@ -72,6 +71,7 @@ org.openapitools.codegen.languages.LuaClientCodegen
|
||||
org.openapitools.codegen.languages.MarkdownDocumentationCodegen
|
||||
org.openapitools.codegen.languages.MysqlSchemaCodegen
|
||||
org.openapitools.codegen.languages.NimClientCodegen
|
||||
org.openapitools.codegen.languages.NodeJSServerCodegen
|
||||
org.openapitools.codegen.languages.NodeJSExpressServerCodegen
|
||||
org.openapitools.codegen.languages.ObjcClientCodegen
|
||||
org.openapitools.codegen.languages.OCamlClientCodegen
|
||||
@@ -116,6 +116,7 @@ org.openapitools.codegen.languages.StaticHtmlGenerator
|
||||
org.openapitools.codegen.languages.StaticHtml2Generator
|
||||
org.openapitools.codegen.languages.Swift4Codegen
|
||||
org.openapitools.codegen.languages.Swift5ClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptAngularClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptAngularJsClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptAureliaClientCodegen
|
||||
@@ -125,4 +126,4 @@ org.openapitools.codegen.languages.TypeScriptInversifyClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptNodeClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptReduxQueryClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class {{unrealModuleName}} : ModuleRules
|
||||
{
|
||||
public {{unrealModuleName}}(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"Http",
|
||||
"Json",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
class {{dllapi}} {{classname}}
|
||||
{
|
||||
public:
|
||||
{{classname}}();
|
||||
~{{classname}}();
|
||||
|
||||
void SetURL(const FString& Url);
|
||||
void AddHeaderParam(const FString& Key, const FString& Value);
|
||||
void ClearHeaderParams();
|
||||
|
||||
{{#operations}}{{#operation}}class {{operationIdCamelCase}}Request;
|
||||
class {{operationIdCamelCase}}Response;
|
||||
{{/operation}}{{/operations}}
|
||||
{{#operations}}{{#operation}}DECLARE_DELEGATE_OneParam(F{{operationIdCamelCase}}Delegate, const {{operationIdCamelCase}}Response&);
|
||||
{{/operation}}{{/operations}}
|
||||
{{#operations}}{{#operation}}{{#description}}/* {{{description}}} */
|
||||
{{/description}}bool {{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate = F{{operationIdCamelCase}}Delegate()) const;
|
||||
{{/operation}}{{/operations}}
|
||||
private:
|
||||
{{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const;
|
||||
{{/operation}}{{/operations}}
|
||||
bool IsValid() const;
|
||||
void HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const;
|
||||
|
||||
FString Url;
|
||||
TMap<FString,FString> AdditionalHeaderParams;
|
||||
};
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,64 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
#include "{{classname}}.h"
|
||||
|
||||
{{#imports}}{{{import}}}
|
||||
{{/imports}}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
/* {{summary}}
|
||||
{{#notes}} *
|
||||
* {{notes}}{{/notes}}
|
||||
*/
|
||||
class {{dllapi}} {{classname}}::{{operationIdCamelCase}}Request : public Request
|
||||
{
|
||||
public:
|
||||
virtual ~{{operationIdCamelCase}}Request() {}
|
||||
void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const final;
|
||||
FString ComputePath() const final;
|
||||
|
||||
{{#allParams}}
|
||||
{{#isEnum}}
|
||||
{{#allowableValues}}
|
||||
enum class {{{enumName}}}
|
||||
{
|
||||
{{#enumVars}}
|
||||
{{name}},
|
||||
{{/enumVars}}
|
||||
};
|
||||
{{/allowableValues}}
|
||||
{{#description}}/* {{{description}}} */
|
||||
{{/description}}{{^required}}TOptional<{{/required}}{{{datatypeWithEnum}}}{{^required}}>{{/required}} {{paramName}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#description}}/* {{{description}}} */
|
||||
{{/description}}{{^required}}TOptional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
|
||||
{{/isEnum}}
|
||||
{{/allParams}}
|
||||
};
|
||||
|
||||
class {{dllapi}} {{classname}}::{{operationIdCamelCase}}Response : public Response
|
||||
{
|
||||
public:
|
||||
virtual ~{{operationIdCamelCase}}Response() {}
|
||||
{{#responses.0}}
|
||||
void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode) final;
|
||||
{{/responses.0}}
|
||||
bool FromJson(const TSharedPtr<FJsonValue>& JsonObject) final;
|
||||
|
||||
{{#returnType}}{{{returnType}}} Content;{{/returnType}}
|
||||
};
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,286 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{classname}}Operations.h"
|
||||
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
#include "{{modelNamePrefix}}Helpers.h"
|
||||
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "Templates/SharedPointer.h"
|
||||
#include "HttpModule.h"
|
||||
#include "PlatformHttp.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
{{#operations}}{{#operation}}
|
||||
{{#allParams}}
|
||||
{{#isEnum}}
|
||||
inline FString ToString(const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
|
||||
{
|
||||
{{#allowableValues}}
|
||||
switch (Value)
|
||||
{
|
||||
{{#enumVars}}
|
||||
case {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}}:
|
||||
return TEXT({{{value}}});
|
||||
{{/enumVars}}
|
||||
}
|
||||
{{/allowableValues}}
|
||||
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Invalid {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}} Value (%d)"), (int)Value);
|
||||
return TEXT("");
|
||||
}
|
||||
|
||||
inline FStringFormatArg ToStringFormatArg(const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
|
||||
{
|
||||
return FStringFormatArg(ToString(Value));
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
|
||||
{
|
||||
WriteJsonValue(Writer, ToString(Value));
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
|
||||
{
|
||||
{{#allowableValues}}
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
{
|
||||
static TMap<FString, {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}> StringToEnum = { {{#enumVars}}
|
||||
{ TEXT({{{value}}}), {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}} },{{/enumVars}} };
|
||||
|
||||
const auto Found = StringToEnum.Find(TmpValue);
|
||||
if(Found)
|
||||
{
|
||||
Value = *Found;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{{/allowableValues}}
|
||||
return false;
|
||||
}
|
||||
|
||||
{{/isEnum}}
|
||||
{{/allParams}}
|
||||
FString {{classname}}::{{operationIdCamelCase}}Request::ComputePath() const
|
||||
{
|
||||
{{^pathParams.0}}
|
||||
FString Path(TEXT("{{{path}}}"));
|
||||
{{/pathParams.0}}
|
||||
{{#pathParams.0}}
|
||||
TMap<FString, FStringFormatArg> PathParams = { {{#pathParams}}
|
||||
{ TEXT("{{baseName}}"), ToStringFormatArg({{paramName}}) }{{#hasMore}},{{/hasMore}}{{/pathParams}} };
|
||||
|
||||
FString Path = FString::Format(TEXT("{{{path}}}"), PathParams);
|
||||
|
||||
{{/pathParams.0}}
|
||||
{{#queryParams.0}}
|
||||
TArray<FString> QueryParams;
|
||||
{{#queryParams}}
|
||||
{{#required}}
|
||||
{{^collectionFormat}}
|
||||
QueryParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}));
|
||||
{{/collectionFormat}}
|
||||
{{#collectionFormat}}
|
||||
QueryParams.Add(FString(TEXT("{{baseName}}=")) + CollectionToUrlString_{{collectionFormat}}({{paramName}}, TEXT("{{baseName}}")));
|
||||
{{/collectionFormat}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
{{^collectionFormat}}
|
||||
if({{paramName}}.IsSet())
|
||||
{
|
||||
QueryParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}.GetValue()));
|
||||
}
|
||||
{{/collectionFormat}}
|
||||
{{#collectionFormat}}
|
||||
if({{paramName}}.IsSet())
|
||||
{
|
||||
QueryParams.Add(FString(TEXT("{{baseName}}=")) + CollectionToUrlString_{{collectionFormat}}({{paramName}}.GetValue(), TEXT("{{baseName}}")));
|
||||
}
|
||||
{{/collectionFormat}}
|
||||
{{/required}}
|
||||
{{/queryParams}}
|
||||
Path += TCHAR('?');
|
||||
Path += FString::Join(QueryParams, TEXT("&"));
|
||||
|
||||
{{/queryParams.0}}
|
||||
return Path;
|
||||
}
|
||||
|
||||
void {{classname}}::{{operationIdCamelCase}}Request::SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const
|
||||
{
|
||||
static const TArray<FString> Consumes = { {{#consumes}}TEXT("{{{mediaType}}}"){{#hasMore}}, {{/hasMore}}{{/consumes}} };
|
||||
//static const TArray<FString> Produces = { {{#produces}}TEXT("{{{mediaType}}}"){{#hasMore}}, {{/hasMore}}{{/produces}} };
|
||||
|
||||
HttpRequest->SetVerb(TEXT("{{httpMethod}}"));
|
||||
{{#headerParams.0}}
|
||||
|
||||
// Header parameters
|
||||
{{#headerParams}}
|
||||
{{#required}}
|
||||
HttpRequest->SetHeader(TEXT("{{baseName}}"), {{paramName}});
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if ({{paramName}}.IsSet())
|
||||
{
|
||||
HttpRequest->SetHeader(TEXT("{{baseName}}"), {{paramName}}.GetValue());
|
||||
}
|
||||
{{/required}}
|
||||
{{/headerParams}}
|
||||
{{/headerParams.0}}
|
||||
|
||||
// Default to Json Body request
|
||||
if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
|
||||
{
|
||||
{{#bodyParams.0}}
|
||||
// Body parameters
|
||||
FString JsonBody;
|
||||
JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
|
||||
|
||||
Writer->WriteObjectStart();
|
||||
{{#bodyParams}}
|
||||
{{#required}}
|
||||
Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{paramName}});
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if ({{paramName}}.IsSet())
|
||||
{
|
||||
Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{paramName}}.GetValue());
|
||||
}
|
||||
{{/required}}
|
||||
{{/bodyParams}}
|
||||
Writer->WriteObjectEnd();
|
||||
Writer->Close();
|
||||
|
||||
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
|
||||
HttpRequest->SetContentAsString(JsonBody);
|
||||
{{/bodyParams.0}}
|
||||
{{#formParams.0}}
|
||||
{{#formParams}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, cannot be used in JsonBody"));
|
||||
{{/formParams}}
|
||||
{{/formParams.0}}
|
||||
}
|
||||
else if (Consumes.Contains(TEXT("multipart/form-data")))
|
||||
{
|
||||
{{#formParams.0}}
|
||||
HttpMultipartFormData FormData;
|
||||
{{#formParams}}
|
||||
{{#isContainer}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Collections are not supported in multipart form"));
|
||||
{{/isContainer}}
|
||||
{{^isContainer}}
|
||||
{{#required}}
|
||||
{{#isFile}}
|
||||
FormData.AddFilePart(TEXT("{{baseName}}"), {{paramName}});
|
||||
{{/isFile}}
|
||||
{{#isBinary}}
|
||||
FormData.AddBinaryPart(TEXT("{{baseName}}"), {{paramName}});
|
||||
{{/isBinary}}
|
||||
{{#isBinary}}
|
||||
{{^isFile}}
|
||||
FormData.AddStringPart(TEXT("{{baseName}}"), *ToUrlString({{paramName}}));
|
||||
{{/isFile}}
|
||||
{{/isBinary}}
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if({{paramName}}.IsSet())
|
||||
{
|
||||
{{#isFile}}
|
||||
FormData.AddFilePart(TEXT("{{baseName}}"), {{paramName}}.GetValue());
|
||||
{{/isFile}}
|
||||
{{#isBinary}}
|
||||
FormData.AddBinaryPart(TEXT("{{baseName}}"), {{paramName}}.GetValue());
|
||||
{{/isBinary}}
|
||||
{{^isBinary}}
|
||||
{{^isFile}}
|
||||
FormData.AddStringPart(TEXT("{{baseName}}"), *ToUrlString({{paramName}}.GetValue()));
|
||||
{{/isFile}}
|
||||
{{/isBinary}}
|
||||
}
|
||||
{{/required}}
|
||||
{{/isContainer}}
|
||||
{{/formParams}}
|
||||
|
||||
FormData.SetupHttpRequest(HttpRequest);
|
||||
{{/formParams.0}}
|
||||
{{#bodyParams.0}}
|
||||
{{#bodyParams}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Body parameter ({{baseName}}) was ignored, not supported in multipart form"));
|
||||
{{/bodyParams}}
|
||||
{{/bodyParams.0}}
|
||||
}
|
||||
else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
|
||||
{
|
||||
{{#formParams.0}}
|
||||
TArray<FString> FormParams;
|
||||
{{#formParams}}
|
||||
{{#isContainer}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Collections are not supported in urlencoded requests"));
|
||||
{{/isContainer}}
|
||||
{{#isFile}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Files are not supported in urlencoded requests"));
|
||||
{{/isFile}}
|
||||
{{^isFile}}
|
||||
{{^isContainer}}
|
||||
{{#required}}
|
||||
FormParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}));
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if({{paramName}}.IsSet())
|
||||
{
|
||||
FormParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}.GetValue()));
|
||||
}
|
||||
{{/required}}
|
||||
{{/isContainer}}
|
||||
{{/isFile}}
|
||||
{{/formParams}}
|
||||
|
||||
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/x-www-form-urlencoded; charset=utf-8"));
|
||||
HttpRequest->SetContentAsString(FString::Join(FormParams, TEXT("&")));
|
||||
{{/formParams.0}}
|
||||
{{#bodyParams.0}}
|
||||
{{#bodyParams}}
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Body parameter ({{baseName}}) was ignored, not supported in urlencoded requests"));
|
||||
{{/bodyParams}}
|
||||
{{/bodyParams.0}}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
|
||||
}
|
||||
}
|
||||
|
||||
{{#responses.0}}
|
||||
void {{classname}}::{{operationIdCamelCase}}Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
|
||||
{
|
||||
Response::SetHttpResponseCode(InHttpResponseCode);
|
||||
switch ((int)InHttpResponseCode)
|
||||
{
|
||||
{{#responses}}
|
||||
case {{code}}:
|
||||
{{#isDefault}}
|
||||
default:
|
||||
{{/isDefault}}
|
||||
SetResponseString(TEXT("{{message}}"));
|
||||
break;
|
||||
{{/responses}}
|
||||
}
|
||||
}
|
||||
{{/responses.0}}
|
||||
|
||||
bool {{classname}}::{{operationIdCamelCase}}Response::FromJson(const TSharedPtr<FJsonValue>& JsonValue)
|
||||
{
|
||||
{{#returnType}}
|
||||
return TryGetJsonValue(JsonValue, Content);
|
||||
{{/returnType}}
|
||||
{{^returnType}}
|
||||
return true;
|
||||
{{/returnType}}
|
||||
}
|
||||
{{/operation}}{{/operations}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,120 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{classname}}.h"
|
||||
|
||||
#include "{{classname}}Operations.h"
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
|
||||
#include "HttpModule.h"
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
{{classname}}::{{classname}}()
|
||||
: Url(TEXT("{{basePath}}"))
|
||||
{
|
||||
}
|
||||
|
||||
{{classname}}::~{{classname}}() {}
|
||||
|
||||
void {{classname}}::SetURL(const FString& InUrl)
|
||||
{
|
||||
Url = InUrl;
|
||||
}
|
||||
|
||||
void {{classname}}::AddHeaderParam(const FString& Key, const FString& Value)
|
||||
{
|
||||
AdditionalHeaderParams.Add(Key, Value);
|
||||
}
|
||||
|
||||
void {{classname}}::ClearHeaderParams()
|
||||
{
|
||||
AdditionalHeaderParams.Reset();
|
||||
}
|
||||
|
||||
bool {{classname}}::IsValid() const
|
||||
{
|
||||
if (Url.IsEmpty())
|
||||
{
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("{{classname}}: Endpoint Url is not set, request cannot be performed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void {{classname}}::HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const
|
||||
{
|
||||
InOutResponse.SetHttpResponse(HttpResponse);
|
||||
InOutResponse.SetSuccessful(bSucceeded);
|
||||
|
||||
if (bSucceeded && HttpResponse.IsValid())
|
||||
{
|
||||
InOutResponse.SetHttpResponseCode((EHttpResponseCodes::Type)HttpResponse->GetResponseCode());
|
||||
FString ContentType = HttpResponse->GetContentType();
|
||||
FString Content;
|
||||
|
||||
if (ContentType == TEXT("application/json"))
|
||||
{
|
||||
Content = HttpResponse->GetContentAsString();
|
||||
|
||||
TSharedPtr<FJsonValue> JsonValue;
|
||||
auto Reader = TJsonReaderFactory<>::Create(Content);
|
||||
|
||||
if (FJsonSerializer::Deserialize(Reader, JsonValue) && JsonValue.IsValid())
|
||||
{
|
||||
if (InOutResponse.FromJson(JsonValue))
|
||||
return; // Successfully parsed
|
||||
}
|
||||
}
|
||||
else if(ContentType == TEXT("text/plain"))
|
||||
{
|
||||
Content = HttpResponse->GetContentAsString();
|
||||
InOutResponse.SetResponseString(Content);
|
||||
return; // Successfully parsed
|
||||
}
|
||||
|
||||
// Report the parse error but do not mark the request as unsuccessful. Data could be partial or malformed, but the request succeeded.
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Failed to deserialize Http response content (type:%s):\n%s"), *ContentType , *Content);
|
||||
return;
|
||||
}
|
||||
|
||||
// By default, assume we failed to establish connection
|
||||
InOutResponse.SetHttpResponseCode(EHttpResponseCodes::RequestTimeout);
|
||||
}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate /*= F{{operationIdCamelCase}}Delegate()*/) const
|
||||
{
|
||||
if (!IsValid())
|
||||
return false;
|
||||
|
||||
TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
|
||||
HttpRequest->SetURL(*(Url + Request.ComputePath()));
|
||||
|
||||
for(const auto& It : AdditionalHeaderParams)
|
||||
{
|
||||
HttpRequest->SetHeader(It.Key, It.Value);
|
||||
}
|
||||
|
||||
Request.SetupHttpRequest(HttpRequest);
|
||||
|
||||
HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate);
|
||||
return HttpRequest->ProcessRequest();
|
||||
}
|
||||
|
||||
void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const
|
||||
{
|
||||
{{operationIdCamelCase}}Response Response;
|
||||
HandleResponse(HttpResponse, bSucceeded, Response);
|
||||
Delegate.ExecuteIfBound(Response);
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,405 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "Misc/Base64.h"
|
||||
|
||||
class IHttpRequest;
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
typedef TSharedRef<TJsonWriter<>> JsonWriter;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class {{dllapi}} HttpFileInput
|
||||
{
|
||||
public:
|
||||
HttpFileInput(const TCHAR* InFilePath);
|
||||
HttpFileInput(const FString& InFilePath);
|
||||
|
||||
// This will automatically set the content type if not already set
|
||||
void SetFilePath(const TCHAR* InFilePath);
|
||||
void SetFilePath(const FString& InFilePath);
|
||||
|
||||
// Optional if it can be deduced from the FilePath
|
||||
void SetContentType(const TCHAR* ContentType);
|
||||
|
||||
HttpFileInput& operator=(const HttpFileInput& Other) = default;
|
||||
HttpFileInput& operator=(const FString& InFilePath) { SetFilePath(*InFilePath); return*this; }
|
||||
HttpFileInput& operator=(const TCHAR* InFilePath) { SetFilePath(InFilePath); return*this; }
|
||||
|
||||
const FString& GetFilePath() const { return FilePath; }
|
||||
const FString& GetContentType() const { return ContentType; }
|
||||
|
||||
// Returns the filename with extension
|
||||
FString GetFilename() const;
|
||||
|
||||
private:
|
||||
FString FilePath;
|
||||
FString ContentType;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class HttpMultipartFormData
|
||||
{
|
||||
public:
|
||||
void SetBoundary(const TCHAR* InBoundary);
|
||||
void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest);
|
||||
|
||||
void AddStringPart(const TCHAR* Name, const TCHAR* Data);
|
||||
void AddJsonPart(const TCHAR* Name, const FString& JsonString);
|
||||
void AddBinaryPart(const TCHAR* Name, const TArray<uint8>& ByteArray);
|
||||
void AddFilePart(const TCHAR* Name, const HttpFileInput& File);
|
||||
|
||||
private:
|
||||
void AppendString(const TCHAR* Str);
|
||||
const FString& GetBoundary() const;
|
||||
|
||||
mutable FString Boundary;
|
||||
TArray<uint8> FormData;
|
||||
|
||||
static const TCHAR* Delimiter;
|
||||
static const TCHAR* Newline;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Decodes Base64Url encoded strings, see https://en.wikipedia.org/wiki/Base64#Variants_summary_table
|
||||
template<typename T>
|
||||
bool Base64UrlDecode(const FString& Base64String, T& Value)
|
||||
{
|
||||
FString TmpCopy(Base64String);
|
||||
TmpCopy.ReplaceInline(TEXT("-"), TEXT("+"));
|
||||
TmpCopy.ReplaceInline(TEXT("_"), TEXT("/"));
|
||||
|
||||
return FBase64::Decode(TmpCopy, Value);
|
||||
}
|
||||
|
||||
// Encodes strings in Base64Url, see https://en.wikipedia.org/wiki/Base64#Variants_summary_table
|
||||
template<typename T>
|
||||
FString Base64UrlEncode(const T& Value)
|
||||
{
|
||||
FString Base64String = FBase64::Encode(Value);
|
||||
Base64String.ReplaceInline(TEXT("+"), TEXT("-"));
|
||||
Base64String.ReplaceInline(TEXT("/"), TEXT("_"));
|
||||
return Base64String;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FStringFormatArg ToStringFormatArg(const T& Value)
|
||||
{
|
||||
return FStringFormatArg(Value);
|
||||
}
|
||||
|
||||
inline FStringFormatArg ToStringFormatArg(const FDateTime& Value)
|
||||
{
|
||||
return FStringFormatArg(Value.ToIso8601());
|
||||
}
|
||||
|
||||
inline FStringFormatArg ToStringFormatArg(const TArray<uint8>& Value)
|
||||
{
|
||||
return FStringFormatArg(Base64UrlEncode(Value));
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_base_of<Model, T>::value, int>::type = 0>
|
||||
inline FString ToString(const T& Value)
|
||||
{
|
||||
return FString::Format(TEXT("{0}"), { ToStringFormatArg(Value) });
|
||||
}
|
||||
|
||||
inline FString ToString(const FString& Value)
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
inline FString ToString(const TArray<uint8>& Value)
|
||||
{
|
||||
return Base64UrlEncode(Value);
|
||||
}
|
||||
|
||||
inline FString ToString(const Model& Value)
|
||||
{
|
||||
FString String;
|
||||
JsonWriter Writer = TJsonWriterFactory<>::Create(&String);
|
||||
Value.WriteJson(Writer);
|
||||
Writer->Close();
|
||||
return String;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString ToUrlString(const T& Value)
|
||||
{
|
||||
return FPlatformHttp::UrlEncode(ToString(Value));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString(const TArray<T>& Collection, const TCHAR* Separator)
|
||||
{
|
||||
FString Output;
|
||||
if(Collection.Num() == 0)
|
||||
return Output;
|
||||
|
||||
Output += ToUrlString(Collection[0]);
|
||||
for(int i = 1; i < Collection.Num(); i++)
|
||||
{
|
||||
Output += FString::Format(TEXT("{0}{1}"), { Separator, *ToUrlString(Collection[i]) });
|
||||
}
|
||||
return Output;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_csv(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
return CollectionToUrlString(Collection, TEXT(","));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_ssv(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
return CollectionToUrlString(Collection, TEXT(" "));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_tsv(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
return CollectionToUrlString(Collection, TEXT("\t"));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_pipes(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
return CollectionToUrlString(Collection, TEXT("|"));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline FString CollectionToUrlString_multi(const TArray<T>& Collection, const TCHAR* BaseName)
|
||||
{
|
||||
FString Output;
|
||||
if(Collection.Num() == 0)
|
||||
return Output;
|
||||
|
||||
Output += FString::Format(TEXT("{0}={1}"), { FStringFormatArg(BaseName), ToUrlString(Collection[0]) });
|
||||
for(int i = 1; i < Collection.Num(); i++)
|
||||
{
|
||||
Output += FString::Format(TEXT("&{0}={1}"), { FStringFormatArg(BaseName), ToUrlString(Collection[i]) });
|
||||
}
|
||||
return Output;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_base_of<Model, T>::value, int>::type = 0>
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const T& Value)
|
||||
{
|
||||
Writer->WriteValue(Value);
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const FDateTime& Value)
|
||||
{
|
||||
Writer->WriteValue(Value.ToIso8601());
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const Model& Value)
|
||||
{
|
||||
Value.WriteJson(Writer);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const TArray<T>& Value)
|
||||
{
|
||||
Writer->WriteArrayStart();
|
||||
for (const auto& Element : Value)
|
||||
{
|
||||
WriteJsonValue(Writer, Element);
|
||||
}
|
||||
Writer->WriteArrayEnd();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const TMap<FString, T>& Value)
|
||||
{
|
||||
Writer->WriteObjectStart();
|
||||
for (const auto& It : Value)
|
||||
{
|
||||
Writer->WriteIdentifierPrefix(It.Key);
|
||||
WriteJsonValue(Writer, It.Value);
|
||||
}
|
||||
Writer->WriteObjectEnd();
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const TSharedPtr<FJsonObject>& Value)
|
||||
{
|
||||
if (Value.IsValid())
|
||||
{
|
||||
FJsonSerializer::Serialize(Value.ToSharedRef(), Writer, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Writer->WriteObjectStart();
|
||||
Writer->WriteObjectEnd();
|
||||
}
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const TArray<uint8>& Value)
|
||||
{
|
||||
Writer->WriteValue(ToString(Value));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonObject>& JsonObject, const FString& Key, T& Value)
|
||||
{
|
||||
const TSharedPtr<FJsonValue> JsonValue = JsonObject->TryGetField(Key);
|
||||
if (JsonValue.IsValid() && !JsonValue->IsNull())
|
||||
{
|
||||
return TryGetJsonValue(JsonValue, Value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonObject>& JsonObject, const FString& Key, TOptional<T>& OptionalValue)
|
||||
{
|
||||
if(JsonObject->HasField(Key))
|
||||
{
|
||||
T Value;
|
||||
if (TryGetJsonValue(JsonObject, Key, Value))
|
||||
{
|
||||
OptionalValue = Value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true; // Absence of optional value is not a parsing error
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, FString& Value)
|
||||
{
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
{
|
||||
Value = TmpValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, FDateTime& Value)
|
||||
{
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
return FDateTime::Parse(TmpValue, Value);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, bool& Value)
|
||||
{
|
||||
bool TmpValue;
|
||||
if (JsonValue->TryGetBool(TmpValue))
|
||||
{
|
||||
Value = TmpValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_base_of<Model, T>::value, int>::type = 0>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, T& Value)
|
||||
{
|
||||
T TmpValue;
|
||||
if (JsonValue->TryGetNumber(TmpValue))
|
||||
{
|
||||
Value = TmpValue;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, Model& Value)
|
||||
{
|
||||
const TSharedPtr<FJsonObject>* Object;
|
||||
if (JsonValue->TryGetObject(Object))
|
||||
return Value.FromJson(*Object);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, TArray<T>& ArrayValue)
|
||||
{
|
||||
const TArray<TSharedPtr<FJsonValue>>* JsonArray;
|
||||
if (JsonValue->TryGetArray(JsonArray))
|
||||
{
|
||||
bool ParseSuccess = true;
|
||||
const int32 Count = JsonArray->Num();
|
||||
ArrayValue.Reset(Count);
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
T TmpValue;
|
||||
ParseSuccess &= TryGetJsonValue((*JsonArray)[i], TmpValue);
|
||||
ArrayValue.Emplace(MoveTemp(TmpValue));
|
||||
}
|
||||
return ParseSuccess;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, TMap<FString, T>& MapValue)
|
||||
{
|
||||
const TSharedPtr<FJsonObject>* Object;
|
||||
if (JsonValue->TryGetObject(Object))
|
||||
{
|
||||
MapValue.Reset();
|
||||
bool ParseSuccess = true;
|
||||
for (const auto& It : (*Object)->Values)
|
||||
{
|
||||
T TmpValue;
|
||||
ParseSuccess &= TryGetJsonValue(It.Value, TmpValue);
|
||||
MapValue.Emplace(It.Key, MoveTemp(TmpValue));
|
||||
}
|
||||
return ParseSuccess;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, TSharedPtr<FJsonObject>& JsonObjectValue)
|
||||
{
|
||||
const TSharedPtr<FJsonObject>* Object;
|
||||
if (JsonValue->TryGetObject(Object))
|
||||
{
|
||||
JsonObjectValue = *Object;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, TArray<uint8>& Value)
|
||||
{
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
{
|
||||
Base64UrlDecode(TmpValue, Value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,187 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{modelNamePrefix}}Helpers.h"
|
||||
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
|
||||
#include "Interfaces/IHttpRequest.h"
|
||||
#include "PlatformHttp.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
HttpFileInput::HttpFileInput(const TCHAR* InFilePath)
|
||||
{
|
||||
SetFilePath(InFilePath);
|
||||
}
|
||||
|
||||
HttpFileInput::HttpFileInput(const FString& InFilePath)
|
||||
{
|
||||
SetFilePath(InFilePath);
|
||||
}
|
||||
|
||||
void HttpFileInput::SetFilePath(const TCHAR* InFilePath)
|
||||
{
|
||||
FilePath = InFilePath;
|
||||
if(ContentType.IsEmpty())
|
||||
{
|
||||
ContentType = FPlatformHttp::GetMimeType(InFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
void HttpFileInput::SetFilePath(const FString& InFilePath)
|
||||
{
|
||||
SetFilePath(*InFilePath);
|
||||
}
|
||||
|
||||
void HttpFileInput::SetContentType(const TCHAR* InContentType)
|
||||
{
|
||||
ContentType = InContentType;
|
||||
}
|
||||
|
||||
FString HttpFileInput::GetFilename() const
|
||||
{
|
||||
return FPaths::GetCleanFilename(FilePath);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const TCHAR* HttpMultipartFormData::Delimiter = TEXT("--");
|
||||
const TCHAR* HttpMultipartFormData::Newline = TEXT("\r\n");
|
||||
|
||||
void HttpMultipartFormData::SetBoundary(const TCHAR* InBoundary)
|
||||
{
|
||||
checkf(Boundary.IsEmpty(), TEXT("Boundary must be set before usage"));
|
||||
Boundary = InBoundary;
|
||||
}
|
||||
|
||||
const FString& HttpMultipartFormData::GetBoundary() const
|
||||
{
|
||||
if (Boundary.IsEmpty())
|
||||
{
|
||||
// Generate a random boundary with enough entropy, should avoid occurences of the boundary in the data.
|
||||
// Since the boundary is generated at every request, in case of failure, retries should succeed.
|
||||
Boundary = FGuid::NewGuid().ToString(EGuidFormats::Short);
|
||||
}
|
||||
|
||||
return Boundary;
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest)
|
||||
{
|
||||
if(HttpRequest->GetVerb() != TEXT("POST"))
|
||||
{
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Expected POST verb when using multipart form data"));
|
||||
}
|
||||
|
||||
// Append final boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Delimiter);
|
||||
|
||||
HttpRequest->SetHeader("Content-Type", FString::Printf(TEXT("multipart/form-data; boundary=%s"), *GetBoundary()));
|
||||
HttpRequest->SetContent(FormData);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AddStringPart(const TCHAR* Name, const TCHAR* Data)
|
||||
{
|
||||
// Add boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header
|
||||
AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name = \"%s\""), Name));
|
||||
AppendString(Newline);
|
||||
AppendString(*FString::Printf(TEXT("Content-Type: text/plain; charset=utf-8")));
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header to body splitter
|
||||
AppendString(Newline);
|
||||
|
||||
// Add Data
|
||||
AppendString(Data);
|
||||
AppendString(Newline);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AddJsonPart(const TCHAR* Name, const FString& JsonString)
|
||||
{
|
||||
// Add boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header
|
||||
AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\""), Name));
|
||||
AppendString(Newline);
|
||||
AppendString(*FString::Printf(TEXT("Content-Type: application/json; charset=utf-8")));
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header to body splitter
|
||||
AppendString(Newline);
|
||||
|
||||
// Add Data
|
||||
AppendString(*JsonString);
|
||||
AppendString(Newline);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AddBinaryPart(const TCHAR* Name, const TArray<uint8>& ByteArray)
|
||||
{
|
||||
// Add boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header
|
||||
AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\""), Name));
|
||||
AppendString(Newline);
|
||||
AppendString(*FString::Printf(TEXT("Content-Type: application/octet-stream")));
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header to body splitter
|
||||
AppendString(Newline);
|
||||
|
||||
// Add Data
|
||||
FormData.Append(ByteArray);
|
||||
AppendString(Newline);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AddFilePart(const TCHAR* Name, const HttpFileInput& File)
|
||||
{
|
||||
TArray<uint8> FileContents;
|
||||
if (!FFileHelper::LoadFileToArray(FileContents, *File.GetFilePath()))
|
||||
{
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Failed to load file (%s)"), *File.GetFilePath());
|
||||
return;
|
||||
}
|
||||
|
||||
// Add boundary
|
||||
AppendString(Delimiter);
|
||||
AppendString(*GetBoundary());
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header
|
||||
AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\""), Name, *File.GetFilename()));
|
||||
AppendString(Newline);
|
||||
AppendString(*FString::Printf(TEXT("Content-Type: %s"), *File.GetContentType()));
|
||||
AppendString(Newline);
|
||||
|
||||
// Add header to body splitter
|
||||
AppendString(Newline);
|
||||
|
||||
// Add Data
|
||||
FormData.Append(FileContents);
|
||||
AppendString(Newline);
|
||||
}
|
||||
|
||||
void HttpMultipartFormData::AppendString(const TCHAR* Str)
|
||||
{
|
||||
FTCHARToUTF8 utf8Str(Str);
|
||||
FormData.Append((uint8*)utf8Str.Get(), utf8Str.Length());
|
||||
}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,59 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "Interfaces/IHttpRequest.h"
|
||||
#include "Interfaces/IHttpResponse.h"
|
||||
#include "Serialization/JsonWriter.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
typedef TSharedRef<TJsonWriter<>> JsonWriter;
|
||||
|
||||
class {{dllapi}} Model
|
||||
{
|
||||
public:
|
||||
virtual ~Model() {}
|
||||
virtual void WriteJson(JsonWriter& Writer) const = 0;
|
||||
virtual bool FromJson(const TSharedPtr<FJsonObject>& JsonObject) = 0;
|
||||
};
|
||||
|
||||
class {{dllapi}} Request
|
||||
{
|
||||
public:
|
||||
virtual ~Request() {}
|
||||
virtual void SetupHttpRequest(const TSharedRef<IHttpRequest>& HttpRequest) const = 0;
|
||||
virtual FString ComputePath() const = 0;
|
||||
};
|
||||
|
||||
class {{dllapi}} Response
|
||||
{
|
||||
public:
|
||||
virtual ~Response() {}
|
||||
virtual bool FromJson(const TSharedPtr<FJsonValue>& JsonObject) = 0;
|
||||
|
||||
void SetSuccessful(bool InSuccessful) { Successful = InSuccessful; }
|
||||
bool IsSuccessful() const { return Successful; }
|
||||
|
||||
virtual void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode);
|
||||
EHttpResponseCodes::Type GetHttpResponseCode() const { return ResponseCode; }
|
||||
|
||||
void SetResponseString(const FString& InResponseString) { ResponseString = InResponseString; }
|
||||
const FString& GetResponseString() const { return ResponseString; }
|
||||
|
||||
void SetHttpResponse(const FHttpResponsePtr& InHttpResponse) { HttpResponse = InHttpResponse; }
|
||||
const FHttpResponsePtr& GetHttpResponse() const { return HttpResponse; }
|
||||
|
||||
private:
|
||||
bool Successful;
|
||||
EHttpResponseCodes::Type ResponseCode;
|
||||
FString ResponseString;
|
||||
FHttpResponsePtr HttpResponse;
|
||||
};
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,21 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
|
||||
{
|
||||
ResponseCode = InHttpResponseCode;
|
||||
SetSuccessful(EHttpResponseCodes::IsOk(InHttpResponseCode));
|
||||
if(InHttpResponseCode == EHttpResponseCodes::RequestTimeout)
|
||||
{
|
||||
SetResponseString(TEXT("Request Timeout"));
|
||||
}
|
||||
}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,51 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "{{modelNamePrefix}}BaseModel.h"
|
||||
{{#imports}}{{{import}}}
|
||||
{{/imports}}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
|
||||
/*
|
||||
* {{classname}}
|
||||
*
|
||||
* {{description}}
|
||||
*/
|
||||
class {{dllapi}} {{classname}} : public Model
|
||||
{
|
||||
public:
|
||||
virtual ~{{classname}}() {}
|
||||
bool FromJson(const TSharedPtr<FJsonObject>& JsonObject) final;
|
||||
void WriteJson(JsonWriter& Writer) const final;
|
||||
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
{{#allowableValues}}
|
||||
enum class {{{enumName}}}
|
||||
{
|
||||
{{#enumVars}}
|
||||
{{name}},
|
||||
{{/enumVars}}
|
||||
};
|
||||
{{/allowableValues}}
|
||||
{{#description}}/* {{{description}}} */
|
||||
{{/description}}{{^required}}TOptional<{{/required}}{{{datatypeWithEnum}}}{{^required}}>{{/required}} {{name}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
{{#description}}/* {{{description}}} */
|
||||
{{/description}}{{^required}}TOptional<{{/required}}{{{datatype}}}{{^required}}>{{/required}} {{name}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
};
|
||||
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,98 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{classname}}.h"
|
||||
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
#include "{{modelNamePrefix}}Helpers.h"
|
||||
|
||||
#include "Templates/SharedPointer.h"
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
namespace {{this}}
|
||||
{
|
||||
{{/cppNamespaceDeclarations}}
|
||||
{{#models}}{{#model}}
|
||||
{{#hasEnums}}
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
inline FString ToString(const {{classname}}::{{{enumName}}}& Value)
|
||||
{
|
||||
{{#allowableValues}}
|
||||
switch (Value)
|
||||
{
|
||||
{{#enumVars}}
|
||||
case {{classname}}::{{{enumName}}}::{{name}}:
|
||||
return TEXT({{{value}}});
|
||||
{{/enumVars}}
|
||||
}
|
||||
{{/allowableValues}}
|
||||
|
||||
UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Invalid {{classname}}::{{{enumName}}} Value (%d)"), (int)Value);
|
||||
return TEXT("");
|
||||
}
|
||||
|
||||
inline FStringFormatArg ToStringFormatArg(const {{classname}}::{{{enumName}}}& Value)
|
||||
{
|
||||
return FStringFormatArg(ToString(Value));
|
||||
}
|
||||
|
||||
inline void WriteJsonValue(JsonWriter& Writer, const {{classname}}::{{{enumName}}}& Value)
|
||||
{
|
||||
WriteJsonValue(Writer, ToString(Value));
|
||||
}
|
||||
|
||||
inline bool TryGetJsonValue(const TSharedPtr<FJsonValue>& JsonValue, {{classname}}::{{{enumName}}}& Value)
|
||||
{
|
||||
FString TmpValue;
|
||||
if (JsonValue->TryGetString(TmpValue))
|
||||
{
|
||||
static TMap<FString, {{classname}}::{{{enumName}}}> StringToEnum = { {{#enumVars}}
|
||||
{ TEXT({{{value}}}), {{classname}}::{{{enumName}}}::{{name}} },{{/enumVars}} };
|
||||
|
||||
const auto Found = StringToEnum.Find(TmpValue);
|
||||
if(Found)
|
||||
{
|
||||
Value = *Found;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
{{/hasEnums}}
|
||||
void {{classname}}::WriteJson(JsonWriter& Writer) const
|
||||
{
|
||||
{{#parent}}
|
||||
#error inheritance not handled right now
|
||||
{{/parent}}
|
||||
Writer->WriteObjectStart();
|
||||
{{#vars}}
|
||||
{{#required}}
|
||||
Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{name}});
|
||||
{{/required}}
|
||||
{{^required}}
|
||||
if ({{name}}.IsSet())
|
||||
{
|
||||
Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{name}}.GetValue());
|
||||
}
|
||||
{{/required}}
|
||||
{{/vars}}
|
||||
Writer->WriteObjectEnd();
|
||||
}
|
||||
|
||||
bool {{classname}}::FromJson(const TSharedPtr<FJsonObject>& JsonObject)
|
||||
{
|
||||
bool ParseSuccess = true;
|
||||
|
||||
{{#vars}}
|
||||
ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("{{baseName}}"), {{name}});
|
||||
{{/vars}}
|
||||
|
||||
return ParseSuccess;
|
||||
}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
@@ -1,15 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#pragma once
|
||||
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "Logging/LogMacros.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(Log{{unrealModuleName}}, Log, All);
|
||||
|
||||
class {{dllapi}} {{unrealModuleName}}Module : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
void StartupModule() final;
|
||||
void ShutdownModule() final;
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
{{>licenseInfo}}
|
||||
#include "{{unrealModuleName}}Module.h"
|
||||
|
||||
IMPLEMENT_MODULE({{unrealModuleName}}Module, {{unrealModuleName}});
|
||||
DEFINE_LOG_CATEGORY(Log{{unrealModuleName}});
|
||||
|
||||
void {{unrealModuleName}}Module::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
void {{unrealModuleName}}Module::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
27
modules/openapi-generator/src/main/resources/nodejs/README.mustache
vendored
Normal file
27
modules/openapi-generator/src/main/resources/nodejs/README.mustache
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# OpenAPI generated server
|
||||
|
||||
## Overview
|
||||
This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
|
||||
|
||||
{{^googleCloudFunctions}}
|
||||
### Running the server
|
||||
To run the server, run:
|
||||
|
||||
```
|
||||
npm start
|
||||
```
|
||||
|
||||
To view the Swagger UI interface:
|
||||
|
||||
```
|
||||
open http://localhost:{{serverPort}}/docs
|
||||
```
|
||||
{{/googleCloudFunctions}}
|
||||
{{#googleCloudFunctions}}
|
||||
### Deploying the function
|
||||
To deploy this module into Google Cloud Functions, you will have to use Google Cloud SDK commandline tool.
|
||||
|
||||
See [Google Cloud Functions quick start guide](https://cloud.google.com/functions/docs/quickstart) and [Deploying Cloud Functions](https://cloud.google.com/functions/docs/deploying/) for the details.
|
||||
{{/googleCloudFunctions}}
|
||||
|
||||
This project leverages the mega-awesome [swagger-tools](https://github.com/apigee-127/swagger-tools) middleware which does most all the work.
|
||||
21
modules/openapi-generator/src/main/resources/nodejs/controller.mustache
vendored
Normal file
21
modules/openapi-generator/src/main/resources/nodejs/controller.mustache
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils/writer.js');
|
||||
{{#operations}}
|
||||
var {{classname}} = require('../{{implFolder}}/{{classname}}Service');
|
||||
{{#operation}}
|
||||
|
||||
module.exports.{{nickname}} = function {{nickname}} (req, res, next) {
|
||||
{{#allParams}}
|
||||
var {{paramName}} = req.swagger.params['{{baseName}}'].value;
|
||||
{{/allParams}}
|
||||
{{classname}}.{{nickname}}({{#allParams}}{{paramName}}{{#hasMore}},{{/hasMore}}{{/allParams}})
|
||||
.then(function (response) {
|
||||
utils.writeJson(res, response);
|
||||
})
|
||||
.catch(function (response) {
|
||||
utils.writeJson(res, response);
|
||||
});
|
||||
};
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
44
modules/openapi-generator/src/main/resources/nodejs/index-gcf.mustache
vendored
Normal file
44
modules/openapi-generator/src/main/resources/nodejs/index-gcf.mustache
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
|
||||
var swaggerTools = require('swagger-tools');
|
||||
var jsyaml = require('js-yaml');
|
||||
var fs = require('fs');
|
||||
|
||||
// swaggerRouter configuration
|
||||
var options = {
|
||||
controllers: './controllers',
|
||||
useStubs: false
|
||||
};
|
||||
|
||||
// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
|
||||
var spec = fs.readFileSync('./api/openapi.yaml', 'utf8');
|
||||
var swaggerDoc = jsyaml.safeLoad(spec);
|
||||
|
||||
function toPromise(f, req, res) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
f(req, res, function(err) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.{{exportedName}} = function(req, res) {
|
||||
swaggerTools.initializeMiddleware(swaggerDoc, function(middleware) {
|
||||
var metadata = middleware.swaggerMetadata();
|
||||
var validator = middleware.swaggerValidator();
|
||||
var router = middleware.swaggerRouter(options);
|
||||
req.url = swaggerDoc.basePath + req.url;
|
||||
toPromise(metadata, req, res).then(function() {
|
||||
return toPromise(validator, req, res);
|
||||
}).then(function() {
|
||||
return toPromise(router, req, res);
|
||||
}).catch(function(err) {
|
||||
console.error(err);
|
||||
res.status(res.statusCode || 400).send(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
44
modules/openapi-generator/src/main/resources/nodejs/index.mustache
vendored
Normal file
44
modules/openapi-generator/src/main/resources/nodejs/index.mustache
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
http = require('http');
|
||||
|
||||
var app = require('connect')();
|
||||
var swaggerTools = require('swagger-tools');
|
||||
var jsyaml = require('js-yaml');
|
||||
var serverPort = {{serverPort}};
|
||||
|
||||
// swaggerRouter configuration
|
||||
var options = {
|
||||
swaggerUi: path.join(__dirname, '/openapi.json'),
|
||||
controllers: path.join(__dirname, './controllers'),
|
||||
useStubs: process.env.NODE_ENV === 'development' // Conditionally turn on stubs (mock mode)
|
||||
};
|
||||
|
||||
// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
|
||||
var spec = fs.readFileSync(path.join(__dirname,'api/openapi.yaml'), 'utf8');
|
||||
var swaggerDoc = jsyaml.safeLoad(spec);
|
||||
|
||||
// Initialize the Swagger middleware
|
||||
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
|
||||
|
||||
// Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
|
||||
app.use(middleware.swaggerMetadata());
|
||||
|
||||
// Validate Swagger requests
|
||||
app.use(middleware.swaggerValidator());
|
||||
|
||||
// Route validated requests to appropriate controller
|
||||
app.use(middleware.swaggerRouter(options));
|
||||
|
||||
// Serve the Swagger documents and Swagger UI
|
||||
app.use(middleware.swaggerUi());
|
||||
|
||||
// Start the server
|
||||
http.createServer(app).listen(serverPort, function () {
|
||||
console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort);
|
||||
console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort);
|
||||
});
|
||||
|
||||
});
|
||||
1
modules/openapi-generator/src/main/resources/nodejs/openapi.mustache
vendored
Normal file
1
modules/openapi-generator/src/main/resources/nodejs/openapi.mustache
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{{{openapi-yaml}}}
|
||||
24
modules/openapi-generator/src/main/resources/nodejs/package.mustache
vendored
Normal file
24
modules/openapi-generator/src/main/resources/nodejs/package.mustache
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "{{projectName}}",
|
||||
"version": "{{appVersion}}",
|
||||
"description": "{{{appDescription}}}",
|
||||
"main": "index.js",
|
||||
{{^googleCloudFunctions}}
|
||||
"scripts": {
|
||||
"prestart": "npm install",
|
||||
"start": "node index.js"
|
||||
},
|
||||
{{/googleCloudFunctions}}
|
||||
"keywords": [
|
||||
"openapi-tools"
|
||||
],
|
||||
"license": "Unlicense",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
{{^googleCloudFunctions}}
|
||||
"connect": "^3.2.0",
|
||||
{{/googleCloudFunctions}}
|
||||
"js-yaml": "^3.3.0",
|
||||
"swagger-tools": "0.10.1"
|
||||
}
|
||||
}
|
||||
44
modules/openapi-generator/src/main/resources/nodejs/service.mustache
vendored
Normal file
44
modules/openapi-generator/src/main/resources/nodejs/service.mustache
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
|
||||
/**
|
||||
{{#summary}}
|
||||
* {{{summary}}}
|
||||
{{/summary}}
|
||||
{{#notes}}
|
||||
* {{{notes}}}
|
||||
{{/notes}}
|
||||
*
|
||||
{{#allParams}}
|
||||
* {{paramName}} {{{dataType}}} {{{description}}}{{^required}} (optional){{/required}}
|
||||
{{/allParams}}
|
||||
{{^returnType}}
|
||||
* no response value expected for this operation
|
||||
{{/returnType}}
|
||||
{{#returnType}}
|
||||
* returns {{{returnType}}}
|
||||
{{/returnType}}
|
||||
**/
|
||||
exports.{{{operationId}}} = function({{#allParams}}{{paramName}}{{#hasMore}},{{/hasMore}}{{/allParams}}) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
{{#returnType}}
|
||||
var examples = {};
|
||||
{{#examples}}
|
||||
examples['{{contentType}}'] = {{{example}}};
|
||||
{{/examples}}
|
||||
if (Object.keys(examples).length > 0) {
|
||||
resolve(examples[Object.keys(examples)[0]]);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
{{/returnType}}
|
||||
{{^returnType}}
|
||||
resolve();
|
||||
{{/returnType}}
|
||||
});
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
43
modules/openapi-generator/src/main/resources/nodejs/writer.mustache
vendored
Normal file
43
modules/openapi-generator/src/main/resources/nodejs/writer.mustache
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
var ResponsePayload = function(code, payload) {
|
||||
this.code = code;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
exports.respondWithCode = function(code, payload) {
|
||||
return new ResponsePayload(code, payload);
|
||||
}
|
||||
|
||||
var writeJson = exports.writeJson = function(response, arg1, arg2) {
|
||||
var code;
|
||||
var payload;
|
||||
|
||||
if(arg1 && arg1 instanceof ResponsePayload) {
|
||||
writeJson(response, arg1.payload, arg1.code);
|
||||
return;
|
||||
}
|
||||
|
||||
if(arg2 && Number.isInteger(arg2)) {
|
||||
code = arg2;
|
||||
}
|
||||
else {
|
||||
if(arg1 && Number.isInteger(arg1)) {
|
||||
code = arg1;
|
||||
}
|
||||
}
|
||||
if(code && arg1) {
|
||||
payload = arg1;
|
||||
}
|
||||
else if(arg1) {
|
||||
payload = arg1;
|
||||
}
|
||||
|
||||
if(!code) {
|
||||
// if no response code given, we default to 200
|
||||
code = 200;
|
||||
}
|
||||
if(typeof payload === 'object') {
|
||||
payload = JSON.stringify(payload, null, 2);
|
||||
}
|
||||
response.writeHead(code, {'Content-Type': 'application/json'});
|
||||
response.end(payload);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
required_properties = set([
|
||||
'_data_store',
|
||||
'_check_type',
|
||||
'_spec_property_naming',
|
||||
'_from_server',
|
||||
'_path_to_item',
|
||||
'_configuration',
|
||||
'_visited_composed_classes',
|
||||
@@ -15,7 +15,7 @@
|
||||
constant_args = {
|
||||
'_check_type': _check_type,
|
||||
'_path_to_item': _path_to_item,
|
||||
'_spec_property_naming': _spec_property_naming,
|
||||
'_from_server': _from_server,
|
||||
'_configuration': _configuration,
|
||||
'_visited_composed_classes': self._visited_composed_classes,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
required_properties = set([
|
||||
'_data_store',
|
||||
'_check_type',
|
||||
'_spec_property_naming',
|
||||
'_from_server',
|
||||
'_path_to_item',
|
||||
'_configuration',
|
||||
'_visited_composed_classes',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@convert_js_args_to_python_args
|
||||
def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
|
||||
def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501
|
||||
"""{{classname}} - a model defined in OpenAPI
|
||||
|
||||
{{#requiredVars}}
|
||||
@@ -26,10 +26,8 @@
|
||||
_path_to_item (tuple/list): This is a list of keys or values to
|
||||
drill down to the model in received_data
|
||||
when deserializing a response
|
||||
_spec_property_naming (bool): True if the variable names in the input data
|
||||
are serialized names, as specified in the OpenAPI document.
|
||||
False if the variable names in the input data
|
||||
are pythonic names, e.g. snake case (default)
|
||||
_from_server (bool): True if the data is from the server
|
||||
False if the data is from the client (default)
|
||||
_configuration (Configuration): the instance to use when
|
||||
deserializing a file_type parameter.
|
||||
If passed, type conversion is attempted
|
||||
@@ -56,7 +54,7 @@
|
||||
|
||||
self._data_store = {}
|
||||
self._check_type = _check_type
|
||||
self._spec_property_naming = _spec_property_naming
|
||||
self._from_server = _from_server
|
||||
self._path_to_item = _path_to_item
|
||||
self._configuration = _configuration
|
||||
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
if self._check_type:
|
||||
value = validate_and_convert_types(
|
||||
value, required_types_mixed, path_to_item, self._spec_property_naming,
|
||||
value, required_types_mixed, path_to_item, self._from_server,
|
||||
self._check_type, configuration=self._configuration)
|
||||
if (name,) in self.allowed_values:
|
||||
check_allowed_values(
|
||||
|
||||
@@ -564,17 +564,15 @@ def order_response_types(required_types):
|
||||
return sorted_types
|
||||
|
||||
|
||||
def remove_uncoercible(required_types_classes, current_item, spec_property_naming,
|
||||
def remove_uncoercible(required_types_classes, current_item, from_server,
|
||||
must_convert=True):
|
||||
"""Only keeps the type conversions that are possible
|
||||
|
||||
Args:
|
||||
required_types_classes (tuple): tuple of classes that are required
|
||||
these should be ordered by COERCION_INDEX_BY_TYPE
|
||||
spec_property_naming (bool): True if the variable names in the input
|
||||
data are serialized names as specified in the OpenAPI document.
|
||||
False if the variables names in the input data are python
|
||||
variable names in PEP-8 snake case.
|
||||
from_server (bool): a boolean of whether the data is from the server
|
||||
if false, the data is from the client
|
||||
current_item (any): the current item (input data) to be converted
|
||||
|
||||
Keyword Args:
|
||||
@@ -604,7 +602,7 @@ def remove_uncoercible(required_types_classes, current_item, spec_property_namin
|
||||
continue
|
||||
|
||||
class_pair = (current_type_simple, required_type_class_simplified)
|
||||
if must_convert and class_pair in COERCIBLE_TYPE_PAIRS[spec_property_naming]:
|
||||
if must_convert and class_pair in COERCIBLE_TYPE_PAIRS[from_server]:
|
||||
results_classes.append(required_type_class)
|
||||
elif class_pair in UPCONVERSION_TYPE_PAIRS:
|
||||
results_classes.append(required_type_class)
|
||||
@@ -779,7 +777,7 @@ def get_discriminator_class(model_class,
|
||||
model_class._composed_schemas.get('allOf', ())
|
||||
for cls in composed_children:
|
||||
# Check if the schema has inherited discriminators.
|
||||
if hasattr(cls, 'discriminator') and cls.discriminator is not None:
|
||||
if cls.discriminator is not None:
|
||||
used_model_class = get_discriminator_class(
|
||||
cls, discr_name, discr_value, cls_visited)
|
||||
if used_model_class is not None:
|
||||
@@ -788,7 +786,7 @@ def get_discriminator_class(model_class,
|
||||
|
||||
|
||||
def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
configuration, spec_property_naming):
|
||||
configuration, from_server):
|
||||
"""Deserializes model_data to model instance.
|
||||
|
||||
Args:
|
||||
@@ -798,10 +796,8 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
check_type (bool): whether to check the data tupe for the values in
|
||||
the model
|
||||
configuration (Configuration): the instance to use to convert files
|
||||
spec_property_naming (bool): True if the variable names in the input
|
||||
data are serialized names as specified in the OpenAPI document.
|
||||
False if the variables names in the input data are python
|
||||
variable names in PEP-8 snake case.
|
||||
from_server (bool): True if the data is from the server
|
||||
False if the data is from the client
|
||||
|
||||
Returns:
|
||||
model instance
|
||||
@@ -815,7 +811,7 @@ def deserialize_model(model_data, model_class, path_to_item, check_type,
|
||||
kw_args = dict(_check_type=check_type,
|
||||
_path_to_item=path_to_item,
|
||||
_configuration=configuration,
|
||||
_spec_property_naming=spec_property_naming)
|
||||
_from_server=from_server)
|
||||
|
||||
if issubclass(model_class, ModelSimple):
|
||||
instance = model_class(value=model_data, **kw_args)
|
||||
@@ -866,7 +862,7 @@ def deserialize_file(response_data, configuration, content_disposition=None):
|
||||
|
||||
|
||||
def attempt_convert_item(input_value, valid_classes, path_to_item,
|
||||
configuration, spec_property_naming, key_type=False,
|
||||
configuration, from_server, key_type=False,
|
||||
must_convert=False, check_type=True):
|
||||
"""
|
||||
Args:
|
||||
@@ -874,10 +870,8 @@ def attempt_convert_item(input_value, valid_classes, path_to_item,
|
||||
valid_classes (any): the classes that are valid
|
||||
path_to_item (list): the path to the item to convert
|
||||
configuration (Configuration): the instance to use to convert files
|
||||
spec_property_naming (bool): True if the variable names in the input
|
||||
data are serialized names as specified in the OpenAPI document.
|
||||
False if the variables names in the input data are python
|
||||
variable names in PEP-8 snake case.
|
||||
from_server (bool): True if data is from the server, False is data is
|
||||
from the client
|
||||
key_type (bool): if True we need to convert a key type (not supported)
|
||||
must_convert (bool): if True we must convert
|
||||
check_type (bool): if True we check the type or the returned data in
|
||||
@@ -893,7 +887,7 @@ def attempt_convert_item(input_value, valid_classes, path_to_item,
|
||||
"""
|
||||
valid_classes_ordered = order_response_types(valid_classes)
|
||||
valid_classes_coercible = remove_uncoercible(
|
||||
valid_classes_ordered, input_value, spec_property_naming)
|
||||
valid_classes_ordered, input_value, from_server)
|
||||
if not valid_classes_coercible or key_type:
|
||||
# we do not handle keytype errors, json will take care
|
||||
# of this for us
|
||||
@@ -905,7 +899,7 @@ def attempt_convert_item(input_value, valid_classes, path_to_item,
|
||||
if issubclass(valid_class, OpenApiModel):
|
||||
return deserialize_model(input_value, valid_class,
|
||||
path_to_item, check_type,
|
||||
configuration, spec_property_naming)
|
||||
configuration, from_server)
|
||||
elif valid_class == file_type:
|
||||
return deserialize_file(input_value, configuration)
|
||||
return deserialize_primitive(input_value, valid_class,
|
||||
@@ -977,7 +971,7 @@ def is_valid_type(input_class_simple, valid_classes):
|
||||
|
||||
|
||||
def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
spec_property_naming, _check_type, configuration=None):
|
||||
from_server, _check_type, configuration=None):
|
||||
"""Raises a TypeError is there is a problem, otherwise returns value
|
||||
|
||||
Args:
|
||||
@@ -988,10 +982,8 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
path_to_item: (list) the path to the data being validated
|
||||
this stores a list of keys or indices to get to the data being
|
||||
validated
|
||||
spec_property_naming (bool): True if the variable names in the input
|
||||
data are serialized names as specified in the OpenAPI document.
|
||||
False if the variables names in the input data are python
|
||||
variable names in PEP-8 snake case.
|
||||
from_server (bool): True if data is from the server
|
||||
False if data is from the client
|
||||
_check_type: (boolean) if true, type will be checked and conversion
|
||||
will be attempted.
|
||||
configuration: (Configuration): the configuration class to use
|
||||
@@ -1019,7 +1011,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
valid_classes,
|
||||
path_to_item,
|
||||
configuration,
|
||||
spec_property_naming,
|
||||
from_server,
|
||||
key_type=False,
|
||||
must_convert=True
|
||||
)
|
||||
@@ -1032,14 +1024,14 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
if len(valid_classes) > 1 and configuration:
|
||||
# there are valid classes which are not the current class
|
||||
valid_classes_coercible = remove_uncoercible(
|
||||
valid_classes, input_value, spec_property_naming, must_convert=False)
|
||||
valid_classes, input_value, from_server, must_convert=False)
|
||||
if valid_classes_coercible:
|
||||
converted_instance = attempt_convert_item(
|
||||
input_value,
|
||||
valid_classes_coercible,
|
||||
path_to_item,
|
||||
configuration,
|
||||
spec_property_naming,
|
||||
from_server,
|
||||
key_type=False,
|
||||
must_convert=False
|
||||
)
|
||||
@@ -1066,7 +1058,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
inner_value,
|
||||
inner_required_types,
|
||||
inner_path,
|
||||
spec_property_naming,
|
||||
from_server,
|
||||
_check_type,
|
||||
configuration=configuration
|
||||
)
|
||||
@@ -1084,7 +1076,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item,
|
||||
inner_val,
|
||||
inner_required_types,
|
||||
inner_path,
|
||||
spec_property_naming,
|
||||
from_server,
|
||||
_check_type,
|
||||
configuration=configuration
|
||||
)
|
||||
@@ -1190,8 +1182,8 @@ def convert_js_args_to_python_args(fn):
|
||||
from functools import wraps
|
||||
@wraps(fn)
|
||||
def wrapped_init(self, *args, **kwargs):
|
||||
spec_property_naming = kwargs.get('_spec_property_naming', False)
|
||||
if spec_property_naming:
|
||||
from_server = kwargs.get('_from_server', False)
|
||||
if from_server:
|
||||
kwargs = change_keys_js_to_python(kwargs, self.__class__)
|
||||
return fn(self, *args, **kwargs)
|
||||
return wrapped_init
|
||||
|
||||
1
modules/openapi-generator/src/main/resources/typescript/.gitignore.mustache
vendored
Normal file
1
modules/openapi-generator/src/main/resources/typescript/.gitignore.mustache
vendored
Normal file
@@ -0,0 +1 @@
|
||||
dist
|
||||
30
modules/openapi-generator/src/main/resources/typescript/README.mustache
vendored
Normal file
30
modules/openapi-generator/src/main/resources/typescript/README.mustache
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
## {{npmName}}@{{npmVersion}}
|
||||
|
||||
This generator creates TypeScript/JavaScript client that utilizes {{framework}}.
|
||||
|
||||
### Building
|
||||
|
||||
To build and compile the typescript sources to javascript use:
|
||||
```
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Publishing
|
||||
|
||||
First build the package then run ```npm publish```
|
||||
|
||||
### Consuming
|
||||
|
||||
navigate to the folder of your consuming project and run one of the following commands.
|
||||
|
||||
_published:_
|
||||
|
||||
```
|
||||
npm install {{npmName}}@{{npmVersion}} --save
|
||||
```
|
||||
|
||||
_unPublished (not recommended):_
|
||||
|
||||
```
|
||||
npm install PATH_TO_GENERATED_PACKAGE --save
|
||||
212
modules/openapi-generator/src/main/resources/typescript/api/api.mustache
vendored
Normal file
212
modules/openapi-generator/src/main/resources/typescript/api/api.mustache
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
// TODO: better import syntax?
|
||||
import { BaseAPIRequestFactory, RequiredError } from './baseapi';
|
||||
import {Configuration} from '../configuration';
|
||||
import { RequestContext, HttpMethod, ResponseContext, HttpFile} from '../http/http';
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
import * as FormData from "form-data";
|
||||
{{/node}}
|
||||
{{/platforms}}
|
||||
import {ObjectSerializer} from '../models/ObjectSerializer';
|
||||
import {ApiException} from './exception';
|
||||
import {isCodeInRange} from '../util';
|
||||
|
||||
{{#imports}}
|
||||
import { {{classname}} } from '..{{filename}}';
|
||||
{{/imports}}
|
||||
{{#operations}}
|
||||
|
||||
/**
|
||||
* {{#description}}{{{description}}}{{/description}}{{^description}}no description{{/description}}
|
||||
*/
|
||||
export class {{classname}}RequestFactory extends BaseAPIRequestFactory {
|
||||
|
||||
{{#operation}}
|
||||
/**
|
||||
{{#notes}}
|
||||
* {{¬es}}
|
||||
{{/notes}}
|
||||
{{#summary}}
|
||||
* {{&summary}}
|
||||
{{/summary}}
|
||||
{{#allParams}}
|
||||
* @param {{paramName}} {{description}}
|
||||
{{/allParams}}
|
||||
*/
|
||||
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: Configuration): RequestContext {
|
||||
let config = options || this.configuration;
|
||||
{{#allParams}}
|
||||
|
||||
{{#required}}
|
||||
// verify required parameter '{{paramName}}' is not null or undefined
|
||||
if ({{paramName}} === null || {{paramName}} === undefined) {
|
||||
throw new RequiredError('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.');
|
||||
}
|
||||
|
||||
{{/required}}
|
||||
{{/allParams}}
|
||||
|
||||
// Path Params
|
||||
const localVarPath = '{{{path}}}'{{#pathParams}}
|
||||
.replace('{' + '{{baseName}}' + '}', encodeURIComponent(String({{paramName}}))){{/pathParams}};
|
||||
|
||||
// Make Request Context
|
||||
const requestContext = config.baseServer.makeRequestContext(localVarPath, HttpMethod.{{httpMethod}});
|
||||
requestContext.setHeaderParam("Accept", "application/json, */*;q=0.8")
|
||||
|
||||
// Query Params
|
||||
{{#queryParams}}
|
||||
if ({{paramName}} !== undefined) {
|
||||
requestContext.setQueryParam("{{baseName}}", ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}", "{{dataFormat}}"));
|
||||
}
|
||||
{{/queryParams}}
|
||||
|
||||
// Header Params
|
||||
{{#headerParams}}
|
||||
requestContext.setHeaderParam("{{baseName}}", ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}", "{{dataFormat}}"));
|
||||
{{/headerParams}}
|
||||
|
||||
// Form Params
|
||||
{{#hasFormParams}}
|
||||
let localVarFormParams = new FormData();
|
||||
{{/hasFormParams}}
|
||||
|
||||
{{#formParams}}
|
||||
{{#isListContainer}}
|
||||
if ({{paramName}}) {
|
||||
{{#isCollectionFormatMulti}}
|
||||
{{paramName}}.forEach((element) => {
|
||||
localVarFormParams.append('{{baseName}}', element as any);
|
||||
})
|
||||
{{/isCollectionFormatMulti}}
|
||||
{{^isCollectionFormatMulti}}
|
||||
// TODO: replace .append with .set
|
||||
localVarFormParams.append('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS["{{collectionFormat}}"]));
|
||||
{{/isCollectionFormatMulti}}
|
||||
}
|
||||
{{/isListContainer}}
|
||||
{{^isListContainer}}
|
||||
if ({{paramName}} !== undefined) {
|
||||
// TODO: replace .append with .set
|
||||
{{^isFile}}
|
||||
localVarFormParams.append('{{baseName}}', {{paramName}} as any);
|
||||
{{/isFile}}
|
||||
{{#isFile}}
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
localVarFormParams.append('{{baseName}}', {{paramName}}.data, {{paramName}}.name);
|
||||
{{/node}}
|
||||
{{#browser}}
|
||||
localVarFormParams.append('{{baseName}}', {{paramName}}, {{paramName}}.name);
|
||||
{{/browser}}
|
||||
{{/platforms}}
|
||||
{{/isFile}}
|
||||
}
|
||||
{{/isListContainer}}
|
||||
{{/formParams}}
|
||||
{{#hasFormParams}}
|
||||
requestContext.setBody(localVarFormParams);
|
||||
{{/hasFormParams}}
|
||||
|
||||
// Body Params
|
||||
{{#bodyParam}}
|
||||
const contentType = ObjectSerializer.getPreferredMediaType([{{#consumes}}
|
||||
"{{{mediaType}}}"{{#hasMore}},{{/hasMore}}
|
||||
{{/consumes}}]);
|
||||
requestContext.setHeaderParam("Content-Type", contentType);
|
||||
const serializedBody = ObjectSerializer.stringify(
|
||||
ObjectSerializer.serialize({{paramName}}, "{{{dataType}}}", "{{dataFormat}}"),
|
||||
contentType
|
||||
);
|
||||
requestContext.setBody(serializedBody);
|
||||
{{/bodyParam}}
|
||||
|
||||
{{#hasAuthMethods}}
|
||||
let authMethod = null;
|
||||
{{/hasAuthMethods}}
|
||||
// Apply auth methods
|
||||
{{#authMethods}}
|
||||
authMethod = config.authMethods["{{name}}"]
|
||||
if (authMethod) {
|
||||
authMethod.applySecurityAuthentication(requestContext);
|
||||
}
|
||||
{{/authMethods}}
|
||||
|
||||
return requestContext;
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
}
|
||||
{{/operations}}
|
||||
|
||||
|
||||
{{#operations}}
|
||||
|
||||
export class {{classname}}ResponseProcessor {
|
||||
|
||||
{{#operation}}
|
||||
/**
|
||||
* Unwraps the actual response sent by the server from the response context and deserializes the response content
|
||||
* to the expected objects
|
||||
*
|
||||
* @params response Response returned by the server for a request to {{nickname}}
|
||||
* @throws ApiException if the response code was not in [200, 299]
|
||||
*/
|
||||
public async {{nickname}}(response: ResponseContext): Promise<{{#returnType}}{{{returnType}}}{{/returnType}} {{^returnType}}void{{/returnType}}> {
|
||||
const contentType = ObjectSerializer.normalizeMediaType(response.headers["content-type"]);
|
||||
{{#responses}}
|
||||
if (isCodeInRange("{{code}}", response.httpStatusCode)) {
|
||||
{{#dataType}}
|
||||
{{#isBinary}}
|
||||
const body: {{{dataType}}} = await response.getBodyAsFile() as any as {{{returnType}}};
|
||||
{{/isBinary}}
|
||||
{{^isBinary}}
|
||||
const body: {{{dataType}}} = ObjectSerializer.deserialize(
|
||||
ObjectSerializer.parse(await response.body.text(), contentType),
|
||||
"{{{dataType}}}", "{{returnFormat}}"
|
||||
) as {{{dataType}}};
|
||||
{{/isBinary}}
|
||||
{{#is2xx}}
|
||||
return body;
|
||||
{{/is2xx}}
|
||||
{{^is2xx}}
|
||||
throw new ApiException<{{{dataType}}}>({{code}}, body);
|
||||
{{/is2xx}}
|
||||
{{/dataType}}
|
||||
{{^dataType}}
|
||||
{{#is2xx}}
|
||||
return;
|
||||
{{/is2xx}}
|
||||
{{^is2xx}}
|
||||
throw new ApiException<string>(response.httpStatusCode, "{{message}}");
|
||||
{{/is2xx}}
|
||||
{{/dataType}}
|
||||
}
|
||||
{{/responses}}
|
||||
|
||||
// Work around for missing responses in specification, e.g. for petstore.yaml
|
||||
if (response.httpStatusCode >= 200 && response.httpStatusCode <= 299) {
|
||||
{{#returnType}}
|
||||
{{#isBinary}}
|
||||
const body: {{{returnType}}} = await response.getBodyAsFile() as any as {{{returnType}}};
|
||||
{{/isBinary}}
|
||||
{{^isBinary}}
|
||||
const body: {{{returnType}}} = ObjectSerializer.deserialize(
|
||||
ObjectSerializer.parse(await response.body.text(), contentType),
|
||||
"{{{returnType}}}", "{{returnFormat}}"
|
||||
) as {{{returnType}}};
|
||||
{{/isBinary}}
|
||||
return body;
|
||||
{{/returnType}}
|
||||
{{^returnType}}
|
||||
return;
|
||||
{{/returnType}}
|
||||
}
|
||||
|
||||
let body = response.body || "";
|
||||
throw new ApiException<string>(response.httpStatusCode, "Unknown API Status Code!\nBody: \"" + body + "\"");
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
}
|
||||
{{/operations}}
|
||||
37
modules/openapi-generator/src/main/resources/typescript/api/baseapi.mustache
vendored
Normal file
37
modules/openapi-generator/src/main/resources/typescript/api/baseapi.mustache
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Configuration } from '../configuration'
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
export const COLLECTION_FORMATS = {
|
||||
csv: ",",
|
||||
ssv: " ",
|
||||
tsv: "\t",
|
||||
pipes: "|",
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @class BaseAPI
|
||||
*/
|
||||
export class BaseAPIRequestFactory {
|
||||
|
||||
constructor(protected configuration: Configuration) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @class RequiredError
|
||||
* @extends {Error}
|
||||
*/
|
||||
export class RequiredError extends Error {
|
||||
name: "RequiredError" = "RequiredError";
|
||||
constructor(public field: string, msg?: string) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
14
modules/openapi-generator/src/main/resources/typescript/api/exception.mustache
vendored
Normal file
14
modules/openapi-generator/src/main/resources/typescript/api/exception.mustache
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Represents an error caused by an api call i.e. it has attributes for a HTTP status code
|
||||
* and the returned body object.
|
||||
*
|
||||
* Example
|
||||
* API returns a ErrorMessageObject whenever HTTP status code is not in [200, 299]
|
||||
* => ApiException(404, someErrorMessageObject)
|
||||
*
|
||||
*/
|
||||
export class ApiException<T> extends Error {
|
||||
public constructor(public code: number, public body: T) {
|
||||
super("HTTP-Code: " + code + "\nMessage: " + JSON.stringify(body))
|
||||
}
|
||||
}
|
||||
66
modules/openapi-generator/src/main/resources/typescript/api/middleware.mustache
vendored
Normal file
66
modules/openapi-generator/src/main/resources/typescript/api/middleware.mustache
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
import {RequestContext, ResponseContext} from './http/http';
|
||||
import { Observable, from } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'./rxjsStub'{{/useRxJS}};
|
||||
|
||||
/**
|
||||
* Defines the contract for a middleware intercepting requests before
|
||||
* they are sent (but after the RequestContext was created)
|
||||
* and before the ResponseContext is unwrapped.
|
||||
*
|
||||
*/
|
||||
export interface Middleware {
|
||||
/**
|
||||
* Modifies the request before the request is sent.
|
||||
*
|
||||
* @param context RequestContext of a request which is about to be sent to the server
|
||||
* @returns an observable of the updated request context
|
||||
*
|
||||
*/
|
||||
pre(context: RequestContext): Observable<RequestContext>;
|
||||
/**
|
||||
* Modifies the returned response before it is deserialized.
|
||||
*
|
||||
* @param context ResponseContext of a sent request
|
||||
* @returns an observable of the modified response context
|
||||
*/
|
||||
post(context: ResponseContext): Observable<ResponseContext>;
|
||||
}
|
||||
|
||||
export class PromiseMiddlewareWrapper implements Middleware {
|
||||
|
||||
public constructor(private middleware: PromiseMiddleware) {
|
||||
|
||||
}
|
||||
|
||||
pre(context: RequestContext): Observable<RequestContext> {
|
||||
return from(this.middleware.pre(context));
|
||||
}
|
||||
|
||||
post(context: ResponseContext): Observable<ResponseContext> {
|
||||
return from(this.middleware.post(context));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the contract for a middleware intercepting requests before
|
||||
* they are sent (but after the RequestContext was created)
|
||||
* and before the ResponseContext is unwrapped.
|
||||
*
|
||||
*/
|
||||
export interface PromiseMiddleware {
|
||||
/**
|
||||
* Modifies the request before the request is sent.
|
||||
*
|
||||
* @param context RequestContext of a request which is about to be sent to the server
|
||||
* @returns an observable of the updated request context
|
||||
*
|
||||
*/
|
||||
pre(context: RequestContext): Promise<RequestContext>;
|
||||
/**
|
||||
* Modifies the returned response before it is deserialized.
|
||||
*
|
||||
* @param context ResponseContext of a sent request
|
||||
* @returns an observable of the modified response context
|
||||
*/
|
||||
post(context: ResponseContext): Promise<ResponseContext>;
|
||||
}
|
||||
152
modules/openapi-generator/src/main/resources/typescript/auth/auth.mustache
vendored
Normal file
152
modules/openapi-generator/src/main/resources/typescript/auth/auth.mustache
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
import {RequestContext} from '../http/http';
|
||||
// typings for btoa are incorrect
|
||||
//@ts-ignore
|
||||
import * as btoa from "btoa";
|
||||
|
||||
/**
|
||||
* Base class for all authentication schemes.
|
||||
*
|
||||
*/
|
||||
export abstract class SecurityAuthentication {
|
||||
|
||||
public constructor(private name: string) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* @return returns the name of the security authentication as specified in OAI
|
||||
*/
|
||||
public getName(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the authentication scheme to the request context
|
||||
*
|
||||
* @params context the request context which should use this authentication scheme
|
||||
*/
|
||||
public abstract applySecurityAuthentication(context: RequestContext): void;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies no authentication.
|
||||
*
|
||||
*/
|
||||
export class NoAuthentication extends SecurityAuthentication {
|
||||
|
||||
public constructor() {
|
||||
super("_no_auth");
|
||||
}
|
||||
|
||||
public applySecurityAuthentication(_context: RequestContext) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies an api key to the request context.
|
||||
*
|
||||
*/
|
||||
export class APIKeyAuthentication extends SecurityAuthentication {
|
||||
|
||||
/**
|
||||
* Configures this api key authentication with the necessary properties
|
||||
*
|
||||
* @param authName: name of this authentication scheme as specified in the swagger.json
|
||||
* @param paramName: Parameter name used for the api key
|
||||
* @param keyLocation: Parameter location, either query, header or cookie.
|
||||
* @param apiKey: The api key to be used for every request
|
||||
*/
|
||||
public constructor(authName: string, private paramName: string, private keyLocation: "query" | "header" | "cookie", private apiKey: string) {
|
||||
super(authName);
|
||||
}
|
||||
|
||||
public applySecurityAuthentication(context: RequestContext) {
|
||||
if (this.keyLocation === "header") {
|
||||
context.setHeaderParam(this.paramName, this.apiKey);
|
||||
} else if (this.keyLocation === "cookie") {
|
||||
context.addCookie(this.paramName, this.apiKey);
|
||||
} else if (this.keyLocation === "query") {
|
||||
context.setQueryParam(this.paramName, this.apiKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies basic http authentication to a request.
|
||||
*
|
||||
*/
|
||||
export class HttpBasicAuthentication extends SecurityAuthentication {
|
||||
|
||||
/**
|
||||
* Configures the http authentication with the required details.
|
||||
*
|
||||
*
|
||||
* @param authName name of the authentication scheme as defined in swagger json
|
||||
* @param username username for http basic authentication
|
||||
* @param password password for http basic authentication
|
||||
*/
|
||||
public constructor(authName: string, private username: string, private password: string) {
|
||||
super(authName);
|
||||
}
|
||||
|
||||
public applySecurityAuthentication(context: RequestContext) {
|
||||
let comb = this.username + ":" + this.password;
|
||||
context.setHeaderParam("Authentication", "Basic " + btoa(comb));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: How to handle oauth2 authentication!
|
||||
export class OAuth2Authentication extends SecurityAuthentication {
|
||||
public constructor(authName: string) {
|
||||
super(authName);
|
||||
}
|
||||
|
||||
public applySecurityAuthentication(context: RequestContext) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
export type AuthMethods = {
|
||||
{{#authMethods}}
|
||||
"{{name}}"?: {{#isApiKey}}APIKeyAuthentication{{/isApiKey}}{{#isHttp}}HttpBasicAuthentication{{/isHttp}}{{#isOAuth}}OAuth2Authentication{{/isOAuth}},
|
||||
{{/authMethods}}
|
||||
}
|
||||
|
||||
export type ApiKeyConfiguration = string;
|
||||
export type HttpBasicConfiguration = { "username": string, "password": string };
|
||||
export type OAuth2Configuration = string;
|
||||
|
||||
export type AuthMethodsConfiguration = { {{#authMethods}}"{{name}}"?:{{#isApiKey}}ApiKeyConfiguration{{/isApiKey}}{{#isHttp}}HttpBasicConfiguration{{/isHttp}}{{#isOAuth}}OAuth2Configuration{{/isOAuth}}, {{/authMethods}} }
|
||||
|
||||
/**
|
||||
* Creates the authentication methods from a swagger description.
|
||||
*
|
||||
*/
|
||||
export function configureAuthMethods(conf: AuthMethodsConfiguration | undefined): AuthMethods {
|
||||
let authMethods: AuthMethods = {
|
||||
}
|
||||
|
||||
if (!conf) {
|
||||
return authMethods;
|
||||
}
|
||||
|
||||
{{#authMethods}}
|
||||
if (conf["{{name}}"]) {
|
||||
{{#isApiKey}}
|
||||
authMethods["{{name}}"] = new APIKeyAuthentication("{{name}}", "{{keyParamName}}", {{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, <string> conf["{{name}}"]);
|
||||
{{/isApiKey}}
|
||||
{{#isBasic}}
|
||||
authMethods["{{name}}"] = new HttpBasicAuthentication("{{name}}", config["{{name}}"]["username"], config["{{name}}"]["password"]);
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}
|
||||
authMethods["{{name}}"] = new OAuth2Authentication("{{name}}");
|
||||
{{/isOAuth}}
|
||||
}
|
||||
|
||||
{{/authMethods}}
|
||||
return authMethods;
|
||||
}
|
||||
67
modules/openapi-generator/src/main/resources/typescript/configuration.mustache
vendored
Normal file
67
modules/openapi-generator/src/main/resources/typescript/configuration.mustache
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
import {HttpLibrary} from './http/http';
|
||||
import {Middleware, PromiseMiddleware, PromiseMiddlewareWrapper} from './middleware';
|
||||
{{#frameworks}}
|
||||
{{#fetch-api}}
|
||||
import {IsomorphicFetchHttpLibrary} from "./http/isomorphic-fetch";
|
||||
{{/fetch-api}}
|
||||
{{#jquery}}
|
||||
import {JQueryHttpLibrary} from "./http/jquery";
|
||||
{{/jquery}}
|
||||
{{/frameworks}}
|
||||
import {ServerConfiguration, server1} from './servers';
|
||||
import {configureAuthMethods, AuthMethods, AuthMethodsConfiguration} from './auth/auth';
|
||||
|
||||
/**
|
||||
* Inetrface with which a configuration object can be configured.
|
||||
*
|
||||
*/
|
||||
export interface ConfigurationParameters {
|
||||
/**
|
||||
* Default server to use
|
||||
*/
|
||||
baseServer?: ServerConfiguration<any>;
|
||||
/**
|
||||
* HTTP library to use e.g. IsomorphicFetch
|
||||
*/
|
||||
httpApi?: HttpLibrary;
|
||||
/**
|
||||
* The middlewares which will be applied to requests and responses
|
||||
*/
|
||||
middleware?: Middleware[]; // middleware to apply before/after fetch requests
|
||||
/**
|
||||
* configures all middlewares using the promise api instead of observables (which Middleware uses)
|
||||
*/
|
||||
promiseMiddleware?: PromiseMiddleware[];
|
||||
/**
|
||||
* Configuration for the available authentication methods
|
||||
*/
|
||||
authMethods?: AuthMethodsConfiguration
|
||||
}
|
||||
|
||||
export class Configuration {
|
||||
|
||||
baseServer: ServerConfiguration<any>;
|
||||
httpApi: HttpLibrary;
|
||||
middleware: Middleware[];
|
||||
authMethods: AuthMethods;
|
||||
|
||||
/**
|
||||
* Creates a new configuration object based on the given configuration.
|
||||
* If a property is not included in conf, a default is used:
|
||||
* - baseServer: server1
|
||||
* - httpApi: IsomorphicFetchHttpLibrary
|
||||
* - middleware: []
|
||||
* - promiseMiddleware: []
|
||||
* - authMethods: {}
|
||||
* @param conf particial configuration
|
||||
*/
|
||||
constructor(conf: ConfigurationParameters = {}) {
|
||||
this.baseServer = conf.baseServer !== undefined ? conf.baseServer : server1;
|
||||
this.httpApi = conf.httpApi || {{#frameworks}}{{#fetch-api}}new IsomorphicFetchHttpLibrary(){{/fetch-api}}{{#jquery}}new JQueryHttpLibrary{{/jquery}}{{/frameworks}}; // TODO: replace with window.fetch if available?
|
||||
this.middleware = conf.middleware || [];
|
||||
this.authMethods = configureAuthMethods(conf.authMethods);
|
||||
if (conf.promiseMiddleware) {
|
||||
conf.promiseMiddleware.forEach(m => this.middleware.push(new PromiseMiddlewareWrapper(m)));
|
||||
}
|
||||
}
|
||||
}
|
||||
52
modules/openapi-generator/src/main/resources/typescript/git_push.sh.mustache
vendored
Executable file
52
modules/openapi-generator/src/main/resources/typescript/git_push.sh.mustache
vendored
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/sh
|
||||
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
|
||||
#
|
||||
# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update"
|
||||
|
||||
git_user_id=$1
|
||||
git_repo_id=$2
|
||||
release_note=$3
|
||||
|
||||
if [ "$git_user_id" = "" ]; then
|
||||
git_user_id="{{{gitUserId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
|
||||
fi
|
||||
|
||||
if [ "$git_repo_id" = "" ]; then
|
||||
git_repo_id="{{{gitRepoId}}}"
|
||||
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
|
||||
fi
|
||||
|
||||
if [ "$release_note" = "" ]; then
|
||||
release_note="{{{releaseNote}}}"
|
||||
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
|
||||
fi
|
||||
|
||||
# Initialize the local directory as a Git repository
|
||||
git init
|
||||
|
||||
# Adds the files in the local repository and stages them for commit.
|
||||
git add .
|
||||
|
||||
# Commits the tracked changes and prepares them to be pushed to a remote repository.
|
||||
git commit -m "$release_note"
|
||||
|
||||
# Sets the new remote
|
||||
git_remote=`git remote`
|
||||
if [ "$git_remote" = "" ]; then # git remote not defined
|
||||
|
||||
if [ "$GIT_TOKEN" = "" ]; then
|
||||
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
|
||||
git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git
|
||||
else
|
||||
git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
git pull origin master
|
||||
|
||||
# Pushes (Forces) the changes in the local repository up to the remote repository
|
||||
echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git"
|
||||
git push origin master 2>&1 | grep -v 'To https'
|
||||
|
||||
246
modules/openapi-generator/src/main/resources/typescript/http/http.mustache
vendored
Normal file
246
modules/openapi-generator/src/main/resources/typescript/http/http.mustache
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
// TODO: evaluate if we can easily get rid of this library
|
||||
import * as FormData from "form-data";
|
||||
{{/node}}
|
||||
{{/platforms}}
|
||||
// typings of url-parse are incorrect...
|
||||
// @ts-ignore
|
||||
import * as URLParse from "url-parse";
|
||||
import { Observable } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub'{{/useRxJS}};
|
||||
|
||||
{{#frameworks}}
|
||||
{{#fetch-api}}
|
||||
export * from './isomorphic-fetch';
|
||||
{{/fetch-api}}
|
||||
{{#jquery}}
|
||||
export * from './jquery';
|
||||
{{/jquery}}
|
||||
{{/frameworks}}
|
||||
|
||||
/**
|
||||
* Represents an HTTP method.
|
||||
*/
|
||||
export enum HttpMethod {
|
||||
GET = "GET",
|
||||
HEAD = "HEAD",
|
||||
POST = "POST",
|
||||
PUT = "PUT",
|
||||
DELETE = "DELETE",
|
||||
CONNECT = "CONNECT",
|
||||
OPTIONS = "OPTIONS",
|
||||
TRACE = "TRACE",
|
||||
PATCH = "PATCH"
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an HTTP file which will be transferred from or to a server.
|
||||
*/
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
export type HttpFile = {
|
||||
data: {{{fileContentDataType}}},
|
||||
name: string
|
||||
};
|
||||
{{/node}}
|
||||
{{#browser}}
|
||||
export type HttpFile = {{{fileContentDataType}}} & { readonly name: string };
|
||||
{{/browser}}
|
||||
{{/platforms}}
|
||||
|
||||
|
||||
export class HttpException extends Error {
|
||||
public constructor(msg: string) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the body of an outgoing HTTP request.
|
||||
*/
|
||||
export type RequestBody = undefined | string | FormData;
|
||||
|
||||
/**
|
||||
* Represents an HTTP request context
|
||||
*/
|
||||
export class RequestContext {
|
||||
private headers: { [key: string]: string } = {};
|
||||
private body: RequestBody = undefined;
|
||||
private url: URLParse;
|
||||
|
||||
/**
|
||||
* Creates the request context using a http method and request resource url
|
||||
*
|
||||
* @param url url of the requested resource
|
||||
* @param httpMethod http method
|
||||
*/
|
||||
public constructor(url: string, private httpMethod: HttpMethod) {
|
||||
this.url = URLParse(url, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the url set in the constructor including the query string
|
||||
*
|
||||
*/
|
||||
public getUrl(): string {
|
||||
return this.url.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the url set in the constructor with this url.
|
||||
*
|
||||
*/
|
||||
public setUrl(url: string) {
|
||||
this.url = URLParse(url, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the body of the http request either as a string or FormData
|
||||
*
|
||||
* Note that setting a body on a HTTP GET, HEAD, DELETE, CONNECT or TRACE
|
||||
* request is discouraged.
|
||||
* https://httpwg.org/http-core/draft-ietf-httpbis-semantics-latest.html#rfc.section.7.3.1
|
||||
*
|
||||
* @param body the body of the request
|
||||
*/
|
||||
public setBody(body: RequestBody) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public getHttpMethod(): HttpMethod {
|
||||
return this.httpMethod;
|
||||
}
|
||||
|
||||
public getHeaders(): { [key: string]: string } {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
public getBody(): RequestBody {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public setQueryParam(name: string, value: string) {
|
||||
let queryObj = this.url.query;
|
||||
queryObj[name] = value;
|
||||
this.url.set("query", queryObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a cookie with the name and value. NO check for duplicate cookies is performed
|
||||
*
|
||||
*/
|
||||
public addCookie(name: string, value: string): void {
|
||||
if (!this.headers["Cookie"]) {
|
||||
this.headers["Cookie"] = "";
|
||||
}
|
||||
this.headers["Cookie"] += name + "=" + value + "; ";
|
||||
}
|
||||
|
||||
public setHeaderParam(key: string, value: string): void {
|
||||
this.headers[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ResponseBody {
|
||||
text(): Promise<string>;
|
||||
binary(): Promise<{{{fileContentDataType}}}>;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to generate a `ResponseBody` from binary data
|
||||
*/
|
||||
export class SelfDecodingBody implements ResponseBody {
|
||||
constructor(private dataSource: Promise<{{{fileContentDataType}}}>) {}
|
||||
|
||||
binary(): Promise<{{{fileContentDataType}}}> {
|
||||
return this.dataSource;
|
||||
}
|
||||
|
||||
async text(): Promise<string> {
|
||||
const data: {{{fileContentDataType}}} = await this.dataSource;
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
return data.toString();
|
||||
{{/node}}
|
||||
{{#browser}}
|
||||
// @ts-ignore
|
||||
if (data.text) {
|
||||
// @ts-ignore
|
||||
return data.text();
|
||||
}
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener("load", () => resolve(reader.result));
|
||||
reader.addEventListener("error", () => reject(reader.error));
|
||||
reader.readAsText(data);
|
||||
});
|
||||
{{/browser}}
|
||||
{{/platforms}}
|
||||
}
|
||||
}
|
||||
|
||||
export class ResponseContext {
|
||||
public constructor(
|
||||
public httpStatusCode: number,
|
||||
public headers: { [key: string]: string },
|
||||
public body: ResponseBody
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Parse header value in the form `value; param1="value1"`
|
||||
*
|
||||
* E.g. for Content-Type or Content-Disposition
|
||||
* Parameter names are converted to lower case
|
||||
* The first parameter is returned with the key `""`
|
||||
*/
|
||||
public getParsedHeader(headerName: string): { [parameter: string]: string } {
|
||||
const result: { [parameter: string]: string } = {};
|
||||
if (!this.headers[headerName]) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const parameters = this.headers[headerName].split(";");
|
||||
for (const parameter of parameters) {
|
||||
let [key, value] = parameter.split("=", 2);
|
||||
key = key.toLowerCase().trim();
|
||||
if (value === undefined) {
|
||||
result[""] = key;
|
||||
} else {
|
||||
value = value.trim();
|
||||
if (value.startsWith('"') && value.endsWith('"')) {
|
||||
value = value.substring(1, value.length - 1);
|
||||
}
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public async getBodyAsFile(): Promise<HttpFile> {
|
||||
const data = await this.body.binary();
|
||||
const fileName = this.getParsedHeader("content-disposition")["filename"] || "";
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
return { data, name: fileName };
|
||||
{{/node}}
|
||||
{{#browser}}
|
||||
const contentType = this.headers["content-type"] || "";
|
||||
try {
|
||||
return new File([data], fileName, { type: contentType });
|
||||
} catch (error) {
|
||||
/** Fallback for when the File constructor is not available */
|
||||
return Object.assign(data, {
|
||||
name: fileName,
|
||||
type: contentType
|
||||
});
|
||||
}
|
||||
{{/browser}}
|
||||
{{/platforms}}
|
||||
}
|
||||
}
|
||||
|
||||
export interface HttpLibrary {
|
||||
send(request: RequestContext): Observable<ResponseContext>;
|
||||
}
|
||||
53
modules/openapi-generator/src/main/resources/typescript/http/isomorphic-fetch.mustache
vendored
Normal file
53
modules/openapi-generator/src/main/resources/typescript/http/isomorphic-fetch.mustache
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
import {HttpLibrary, RequestContext, ResponseContext} from './http';
|
||||
import { from, Observable } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub'{{/useRxJS}};
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
import fetch from "node-fetch";
|
||||
{{/node}}
|
||||
{{#browser}}
|
||||
import "whatwg-fetch";
|
||||
{{/browser}}
|
||||
{{/platforms}}
|
||||
|
||||
export class IsomorphicFetchHttpLibrary implements HttpLibrary {
|
||||
|
||||
public send(request: RequestContext): Observable<ResponseContext> {
|
||||
let method = request.getHttpMethod().toString();
|
||||
let body = request.getBody();
|
||||
|
||||
const resultPromise = fetch(request.getUrl(), {
|
||||
method: method,
|
||||
body: body as any,
|
||||
headers: request.getHeaders(),
|
||||
{{#platforms}}
|
||||
{{#browser}}
|
||||
credentials: "same-origin"
|
||||
{{/browser}}
|
||||
{{/platforms}}
|
||||
}).then((resp: any) => {
|
||||
const headers: { [name: string]: string } = {};
|
||||
resp.headers.forEach((value: string, name: string) => {
|
||||
headers[name] = value;
|
||||
});
|
||||
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
const body = {
|
||||
text: () => resp.text(),
|
||||
binary: () => resp.buffer()
|
||||
};
|
||||
{{/node}}
|
||||
{{^node}}
|
||||
const body = {
|
||||
text: () => resp.text(),
|
||||
binary: () => resp.blob()
|
||||
};
|
||||
{{/node}}
|
||||
{{/platforms}}
|
||||
return new ResponseContext(resp.status, headers, body);
|
||||
});
|
||||
|
||||
return from<Promise<ResponseContext>>(resultPromise);
|
||||
|
||||
}
|
||||
}
|
||||
87
modules/openapi-generator/src/main/resources/typescript/http/jquery.mustache
vendored
Normal file
87
modules/openapi-generator/src/main/resources/typescript/http/jquery.mustache
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
import { HttpLibrary, RequestContext, ResponseContext, HttpException, SelfDecodingBody } from './http';
|
||||
import * as e6p from 'es6-promise'
|
||||
import { from, Observable } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub'{{/useRxJS}};
|
||||
e6p.polyfill();
|
||||
import * as $ from 'jquery';
|
||||
|
||||
|
||||
export class JQueryHttpLibrary implements HttpLibrary {
|
||||
|
||||
public send(request: RequestContext): Observable<ResponseContext> {
|
||||
let method = request.getHttpMethod().toString();
|
||||
let body = request.getBody();
|
||||
let headerParams = request.getHeaders()
|
||||
|
||||
let requestOptions: any = {
|
||||
url: request.getUrl(),
|
||||
type: method,
|
||||
headers: request.getHeaders(),
|
||||
processData: false,
|
||||
xhrFields: { withCredentials: true },
|
||||
data: body
|
||||
};
|
||||
|
||||
// If we want a blob, we have to set the xhrFields' responseType AND add a
|
||||
// custom converter to overwrite the default deserialization of JQuery...
|
||||
requestOptions["xhrFields"] = { responseType: 'blob' };
|
||||
requestOptions["converters"] = {}
|
||||
requestOptions["converters"]["* blob"] = (result:any) => result;
|
||||
requestOptions["dataType"] = "blob";
|
||||
|
||||
|
||||
if (request.getHeaders()['Content-Type']) {
|
||||
requestOptions.contentType = headerParams['Content-Type'];
|
||||
}
|
||||
requestOptions.dataFilter = ((headerParams: { [key:string]: string}) => {
|
||||
return (data: string, type: string) => {
|
||||
if (headerParams["Accept"] == "application/json" && data == "") {
|
||||
return "{}"
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
}
|
||||
})(headerParams);
|
||||
|
||||
if (request.getHeaders()["Cookie"]) {
|
||||
throw new HttpException("Setting the \"Cookie\"-Header field is blocked by every major browser when using jquery.ajax requests. Please switch to another library like fetch to enable this option");
|
||||
}
|
||||
|
||||
if (body && body.constructor.name == "FormData") {
|
||||
requestOptions.contentType = false;
|
||||
}
|
||||
|
||||
const sentRequest = $.ajax(requestOptions);
|
||||
|
||||
const resultPromise = new Promise<ResponseContext>((resolve, reject) => {
|
||||
sentRequest.done((data, _, jqXHR) => {
|
||||
const result = new ResponseContext(
|
||||
jqXHR.status,
|
||||
this.getResponseHeaders(jqXHR),
|
||||
new SelfDecodingBody(Promise.resolve(data))
|
||||
);
|
||||
resolve(result);
|
||||
})
|
||||
sentRequest.fail((jqXHR: any) => {
|
||||
const headers = this.getResponseHeaders(jqXHR)
|
||||
const result = new ResponseContext(jqXHR.status, headers, jqXHR.responseText);
|
||||
resolve(result);
|
||||
})
|
||||
})
|
||||
return from(resultPromise);
|
||||
}
|
||||
|
||||
private getResponseHeaders(jqXHR: any): { [key: string]: string } {
|
||||
const responseHeaders: { [key: string]: string } = {};
|
||||
var headers = jqXHR.getAllResponseHeaders();
|
||||
headers = headers.split("\n");
|
||||
headers.forEach(function (header: any) {
|
||||
header = header.split(": ");
|
||||
var key = header.shift();
|
||||
if (key.length == 0) return
|
||||
// chrome60+ force lowercase, other browsers can be different
|
||||
key = key.toLowerCase();
|
||||
responseHeaders[key] = header.join(": ");
|
||||
});
|
||||
return responseHeaders
|
||||
}
|
||||
}
|
||||
57
modules/openapi-generator/src/main/resources/typescript/http/servers.mustache
vendored
Normal file
57
modules/openapi-generator/src/main/resources/typescript/http/servers.mustache
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
import {RequestContext, HttpMethod} from './http/http';
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents the configuration of a server including its
|
||||
* url template and variable configuration based on the url.
|
||||
*
|
||||
*/
|
||||
export class ServerConfiguration<T> {
|
||||
|
||||
public constructor(private url: string, private variableConfiguration: T) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the variables of this server.
|
||||
*
|
||||
* @param variableConfiguration a partial variable configuration for the variables contained in the url
|
||||
*/
|
||||
public setVariables(variableConfiguration: Partial<T>) {
|
||||
for (const key in variableConfiguration) {
|
||||
const val = variableConfiguration[key]
|
||||
// We know that val isn't undefined here - hopefully
|
||||
if (val !== undefined) {
|
||||
this.variableConfiguration[key] = val as T[Extract<keyof T, string>];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getConfiguration(): T {
|
||||
return this.variableConfiguration
|
||||
}
|
||||
|
||||
private getUrl() {
|
||||
let replacedUrl = this.url;
|
||||
for (const key in this.variableConfiguration) {
|
||||
var re = new RegExp("{" + key + "}","g");
|
||||
replacedUrl = replacedUrl.replace(re, this.variableConfiguration[key].toString());
|
||||
}
|
||||
return replacedUrl
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new request context for this server using the url with variables
|
||||
* replaced with their respective values and the endpoint of the request appended.
|
||||
*
|
||||
* @param endpoint the endpoint to be queried on the server
|
||||
* @param httpMethod httpMethod to be used
|
||||
*
|
||||
*/
|
||||
public makeRequestContext(endpoint: string, httpMethod: HttpMethod): RequestContext {
|
||||
return new RequestContext(this.getUrl() + endpoint, httpMethod);
|
||||
}
|
||||
}
|
||||
|
||||
{{#servers}}
|
||||
export const server{{-index}} = new ServerConfiguration<{ {{#variables}} "{{name}}": {{#enumValues}}"{{.}}"{{^-last}} | {{/-last}}{{/enumValues}}{{^enumValues}}string{{/enumValues}}{{^-last}},{{/-last}} {{/variables}} }>("{{url}}", { {{#variables}} "{{name}}": "{{defaultValue}}" {{^-last}},{{/-last}}{{/variables}} })
|
||||
{{/servers}}
|
||||
17
modules/openapi-generator/src/main/resources/typescript/index.mustache
vendored
Normal file
17
modules/openapi-generator/src/main/resources/typescript/index.mustache
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import 'es6-promise/auto';
|
||||
|
||||
export * from './http/http';
|
||||
export * from './auth/auth';
|
||||
export * from './models/all';
|
||||
export { Configuration} from './configuration'
|
||||
export * from './apis/exception';
|
||||
export * from './servers';
|
||||
|
||||
{{#useRxJS}}
|
||||
export * from './types/ObservableAPI';
|
||||
export { Middleware } from './middleware';
|
||||
{{/useRxJS}}
|
||||
{{^useRxJS}}
|
||||
export * from './types/PromiseAPI';
|
||||
export { PromiseMiddleware as Middleware } from './middleware';
|
||||
{{/useRxJS}}
|
||||
@@ -5,7 +5,7 @@
|
||||
* {{#version}}OpenAPI spec version: {{{version}}}{{/version}}
|
||||
* {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}}
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator
|
||||
* https://github.com/OpenAPITools/openapi-generator
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
240
modules/openapi-generator/src/main/resources/typescript/model/ObjectSerializer.mustache
vendored
Normal file
240
modules/openapi-generator/src/main/resources/typescript/model/ObjectSerializer.mustache
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
export * from './{{{ classFilename }}}';
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
import { {{classname}}{{#hasEnums}}{{#vars}}{{#isEnum}}, {{classname}}{{enumName}} {{/isEnum}} {{/vars}}{{/hasEnums}} } from './{{{ classFilename }}}';
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
||||
/* tslint:disable:no-unused-variable */
|
||||
let primitives = [
|
||||
"string",
|
||||
"boolean",
|
||||
"double",
|
||||
"integer",
|
||||
"long",
|
||||
"float",
|
||||
"number",
|
||||
"any"
|
||||
];
|
||||
|
||||
const supportedMediaTypes: { [mediaType: string]: number } = {
|
||||
"application/json": Infinity,
|
||||
"application/octet-stream": 0
|
||||
}
|
||||
|
||||
|
||||
let enumsMap: Set<string> = new Set<string>([
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#hasEnums}}
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
"{{classname}}{{enumName}}",
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
{{/hasEnums}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
]);
|
||||
|
||||
let typeMap: {[index: string]: any} = {
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
"{{classname}}": {{classname}},
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
}
|
||||
|
||||
export class ObjectSerializer {
|
||||
public static findCorrectType(data: any, expectedType: string) {
|
||||
if (data == undefined) {
|
||||
return expectedType;
|
||||
} else if (primitives.indexOf(expectedType.toLowerCase()) !== -1) {
|
||||
return expectedType;
|
||||
} else if (expectedType === "Date") {
|
||||
return expectedType;
|
||||
} else {
|
||||
if (enumsMap.has(expectedType)) {
|
||||
return expectedType;
|
||||
}
|
||||
|
||||
if (!typeMap[expectedType]) {
|
||||
return expectedType; // w/e we don't know the type
|
||||
}
|
||||
|
||||
// Check the discriminator
|
||||
let discriminatorProperty = typeMap[expectedType].discriminator;
|
||||
if (discriminatorProperty == null) {
|
||||
return expectedType; // the type does not have a discriminator. use it.
|
||||
} else {
|
||||
if (data[discriminatorProperty]) {
|
||||
var discriminatorType = data[discriminatorProperty];
|
||||
if(typeMap[discriminatorType]){
|
||||
return discriminatorType; // use the type given in the discriminator
|
||||
} else {
|
||||
return expectedType; // discriminator did not map to a type
|
||||
}
|
||||
} else {
|
||||
return expectedType; // discriminator was not present (or an empty string)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static serialize(data: any, type: string, format: string) {
|
||||
if (data == undefined) {
|
||||
return data;
|
||||
} else if (primitives.indexOf(type.toLowerCase()) !== -1) {
|
||||
return data;
|
||||
} else if (type.lastIndexOf("Array<", 0) === 0) { // string.startsWith pre es6
|
||||
let subType: string = type.replace("Array<", ""); // Array<Type> => Type>
|
||||
subType = subType.substring(0, subType.length - 1); // Type> => Type
|
||||
let transformedData: any[] = [];
|
||||
for (let index in data) {
|
||||
let date = data[index];
|
||||
transformedData.push(ObjectSerializer.serialize(date, subType, format));
|
||||
}
|
||||
return transformedData;
|
||||
} else if (type === "Date") {
|
||||
if (format == "date") {
|
||||
let month = data.getMonth()+1
|
||||
month = month < 10 ? "0" + month.toString() : month.toString()
|
||||
let day = data.getDate();
|
||||
day = day < 10 ? "0" + day.toString() : day.toString();
|
||||
|
||||
return data.getFullYear() + "-" + month + "-" + day;
|
||||
} else {
|
||||
return data.toISOString();
|
||||
}
|
||||
} else {
|
||||
if (enumsMap.has(type)) {
|
||||
return data;
|
||||
}
|
||||
if (!typeMap[type]) { // in case we dont know the type
|
||||
return data;
|
||||
}
|
||||
|
||||
// Get the actual type of this object
|
||||
type = this.findCorrectType(data, type);
|
||||
|
||||
// get the map for the correct type.
|
||||
let attributeTypes = typeMap[type].getAttributeTypeMap();
|
||||
let instance: {[index: string]: any} = {};
|
||||
for (let index in attributeTypes) {
|
||||
let attributeType = attributeTypes[index];
|
||||
instance[attributeType.baseName] = ObjectSerializer.serialize(data[attributeType.name], attributeType.type, attributeType.format);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static deserialize(data: any, type: string, format: string) {
|
||||
// polymorphism may change the actual type.
|
||||
type = ObjectSerializer.findCorrectType(data, type);
|
||||
if (data == undefined) {
|
||||
return data;
|
||||
} else if (primitives.indexOf(type.toLowerCase()) !== -1) {
|
||||
return data;
|
||||
} else if (type.lastIndexOf("Array<", 0) === 0) { // string.startsWith pre es6
|
||||
let subType: string = type.replace("Array<", ""); // Array<Type> => Type>
|
||||
subType = subType.substring(0, subType.length - 1); // Type> => Type
|
||||
let transformedData: any[] = [];
|
||||
for (let index in data) {
|
||||
let date = data[index];
|
||||
transformedData.push(ObjectSerializer.deserialize(date, subType, format));
|
||||
}
|
||||
return transformedData;
|
||||
} else if (type === "Date") {
|
||||
return new Date(data);
|
||||
} else {
|
||||
if (enumsMap.has(type)) {// is Enum
|
||||
return data;
|
||||
}
|
||||
|
||||
if (!typeMap[type]) { // dont know the type
|
||||
return data;
|
||||
}
|
||||
let instance = new typeMap[type]();
|
||||
let attributeTypes = typeMap[type].getAttributeTypeMap();
|
||||
for (let index in attributeTypes) {
|
||||
let attributeType = attributeTypes[index];
|
||||
instance[attributeType.name] = ObjectSerializer.deserialize(data[attributeType.baseName], attributeType.type, attributeType.format);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Normalize media type
|
||||
*
|
||||
* We currently do not handle any media types attributes, i.e. anything
|
||||
* after a semicolon. All content is assumed to be UTF-8 compatible.
|
||||
*/
|
||||
public static normalizeMediaType(mediaType: string | undefined): string | undefined {
|
||||
if (mediaType === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return mediaType.split(";")[0].trim().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* From a list of possible media types, choose the one we can handle best.
|
||||
*
|
||||
* The order of the given media types does not have any impact on the choice
|
||||
* made.
|
||||
*/
|
||||
public static getPreferredMediaType(mediaTypes: Array<string>): string {
|
||||
/** According to OAS 3 we should default to json */
|
||||
if (!mediaTypes) {
|
||||
return "application/json";
|
||||
}
|
||||
|
||||
const normalMediaTypes = mediaTypes.map(this.normalizeMediaType);
|
||||
let selectedMediaType: string | undefined = undefined;
|
||||
let selectedRank: number = -Infinity;
|
||||
for (const mediaType of normalMediaTypes) {
|
||||
if (supportedMediaTypes[mediaType!] > selectedRank) {
|
||||
selectedMediaType = mediaType;
|
||||
selectedRank = supportedMediaTypes[mediaType!];
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedMediaType === undefined) {
|
||||
throw new Error("None of the given media types are supported: " + mediaTypes.join(", "));
|
||||
}
|
||||
|
||||
return selectedMediaType!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert data to a string according the given media type
|
||||
*/
|
||||
public static stringify(data: any, mediaType: string): string {
|
||||
if (mediaType === "application/json") {
|
||||
return JSON.stringify(data);
|
||||
}
|
||||
|
||||
throw new Error("The mediaType " + mediaType + " is not supported by ObjectSerializer.stringify.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse data from a string according to the given media type
|
||||
*/
|
||||
public static parse(rawData: string, mediaType: string | undefined) {
|
||||
if (mediaType === undefined) {
|
||||
throw new Error("Cannot parse content. No Content-Type defined.");
|
||||
}
|
||||
|
||||
if (mediaType === "application/json") {
|
||||
return JSON.parse(rawData);
|
||||
}
|
||||
|
||||
throw new Error("The mediaType " + mediaType + " is not supported by ObjectSerializer.parse.");
|
||||
}
|
||||
}
|
||||
79
modules/openapi-generator/src/main/resources/typescript/model/model.mustache
vendored
Normal file
79
modules/openapi-generator/src/main/resources/typescript/model/model.mustache
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
{{>licenseInfo}}
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#tsImports}}
|
||||
import { {{classname}} } from './{{filename}}';
|
||||
{{/tsImports}}
|
||||
import { HttpFile } from '../http/http';
|
||||
|
||||
{{#description}}
|
||||
/**
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/description}}
|
||||
export class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{
|
||||
{{#vars}}
|
||||
{{#description}}
|
||||
/**
|
||||
* {{{description}}}
|
||||
*/
|
||||
{{/description}}
|
||||
'{{name}}'{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}};
|
||||
{{/vars}}
|
||||
|
||||
{{#discriminator}}
|
||||
static readonly discriminator: string | undefined = "{{discriminatorName}}";
|
||||
{{/discriminator}}
|
||||
{{^discriminator}}
|
||||
static readonly discriminator: string | undefined = undefined;
|
||||
{{/discriminator}}
|
||||
|
||||
{{^isArrayModel}}
|
||||
static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
|
||||
{{#vars}}
|
||||
{
|
||||
"name": "{{name}}",
|
||||
"baseName": "{{baseName}}",
|
||||
"type": "{{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}",
|
||||
"format": "{{dataFormat}}"
|
||||
}{{#hasMore}},
|
||||
{{/hasMore}}
|
||||
{{/vars}}
|
||||
];
|
||||
|
||||
static getAttributeTypeMap() {
|
||||
{{#parent}}
|
||||
return super.getAttributeTypeMap().concat({{classname}}.attributeTypeMap);
|
||||
{{/parent}}
|
||||
{{^parent}}
|
||||
return {{classname}}.attributeTypeMap;
|
||||
{{/parent}}
|
||||
}
|
||||
{{/isArrayModel}}
|
||||
|
||||
public constructor() {
|
||||
{{#parent}}
|
||||
super();
|
||||
{{/parent}}
|
||||
{{#allVars}}
|
||||
{{#discriminatorValue}}
|
||||
this.{{name}} = "{{discriminatorValue}}";
|
||||
{{/discriminatorValue}}
|
||||
{{/allVars}}
|
||||
{{#discriminatorName}}
|
||||
this.{{discriminatorName}} = "{{classname}}";
|
||||
{{/discriminatorName}}
|
||||
}
|
||||
}
|
||||
|
||||
{{#hasEnums}}
|
||||
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
export type {{classname}}{{enumName}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}};
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
|
||||
{{/hasEnums}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
5
modules/openapi-generator/src/main/resources/typescript/model/models_all.mustache
vendored
Normal file
5
modules/openapi-generator/src/main/resources/typescript/model/models_all.mustache
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
export * from './{{{ classFilename }}}'
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
58
modules/openapi-generator/src/main/resources/typescript/package.mustache
vendored
Normal file
58
modules/openapi-generator/src/main/resources/typescript/package.mustache
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "{{npmName}}",
|
||||
"version": "{{npmVersion}}",
|
||||
"description": "OpenAPI client for {{npmName}}",
|
||||
"author": "OpenAPI-Generator Contributors",
|
||||
"keywords": [
|
||||
"fetch",
|
||||
"typescript",
|
||||
"openapi-client",
|
||||
"openapi-generator"
|
||||
],
|
||||
"license": "Unlicense",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
{{#frameworks}}
|
||||
{{#fetch-api}}
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
"node-fetch": "^2.6.0",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
{{/node}}
|
||||
{{#browser}}
|
||||
"whatwg-fetch": "^3.0.0",
|
||||
{{/browser}}
|
||||
{{/platforms}}
|
||||
{{/fetch-api}}
|
||||
{{#jquery}}
|
||||
"@types/jquery": "^3.3.29",
|
||||
"jquery": "^3.4.1",
|
||||
{{/jquery}}
|
||||
{{/frameworks}}
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
"@types/node": "*",
|
||||
"form-data": "^2.5.0",
|
||||
{{/node}}
|
||||
{{/platforms}}
|
||||
{{#useRxJS}}
|
||||
"rxjs": "^6.4.0",
|
||||
{{/useRxJS}}
|
||||
"btoa": "^1.2.1",
|
||||
"es6-promise": "^4.2.4",
|
||||
"url-parse": "^1.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^2.9.2"
|
||||
}{{#npmRepository}},{{/npmRepository}}
|
||||
{{#npmRepository}}
|
||||
"publishConfig":{
|
||||
"registry":"{{npmRepository}}"
|
||||
}
|
||||
{{/npmRepository}}
|
||||
}
|
||||
27
modules/openapi-generator/src/main/resources/typescript/rxjsStub.mustache
vendored
Normal file
27
modules/openapi-generator/src/main/resources/typescript/rxjsStub.mustache
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
export class Observable<T> {
|
||||
constructor(private promise: Promise<T>) {}
|
||||
|
||||
toPromise() {
|
||||
return this.promise;
|
||||
}
|
||||
|
||||
pipe<S>(callback: (value: T) => S | Promise<S>): Observable<S> {
|
||||
return new Observable(this.promise.then(callback));
|
||||
}
|
||||
}
|
||||
|
||||
export function from<T>(promise: Promise<any>) {
|
||||
return new Observable(promise);
|
||||
}
|
||||
|
||||
export function of<T>(value: T) {
|
||||
return new Observable<T>(Promise.resolve(value));
|
||||
}
|
||||
|
||||
export function mergeMap<T, S>(callback: (value: T) => Observable<S>) {
|
||||
return (value: T) => callback(value).toPromise();
|
||||
}
|
||||
|
||||
export function map(callback: any) {
|
||||
return callback;
|
||||
}
|
||||
36
modules/openapi-generator/src/main/resources/typescript/tsconfig.mustache
vendored
Normal file
36
modules/openapi-generator/src/main/resources/typescript/tsconfig.mustache
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
/* Basic Options */
|
||||
"target": "{{#supportsES6}}es6{{/supportsES6}}{{^supportsES6}}es5{{/supportsES6}}",
|
||||
"module": "{{#supportsES6}}es6{{/supportsES6}}{{^supportsES6}}commonjs{{/supportsES6}}",
|
||||
"declaration": true,
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": false, /* Report errors on unused locals. */ // TODO: reenable (unused imports!)
|
||||
"noUnusedParameters": false, /* Report errors on unused parameters. */ // TODO: set to true again
|
||||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
"removeComments": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"noLib": false,
|
||||
{{#platforms}}
|
||||
{{#node}}
|
||||
"lib": [ "es6" ]
|
||||
{{/node}}
|
||||
{{#browser}}
|
||||
"lib": [ "es6", "dom" ]
|
||||
{{/browser}}
|
||||
{{/platforms}}
|
||||
},
|
||||
"exclude": [
|
||||
"dist",
|
||||
"node_modules"
|
||||
],
|
||||
"filesGlob": [
|
||||
"./**/*.ts",
|
||||
]
|
||||
|
||||
}
|
||||
67
modules/openapi-generator/src/main/resources/typescript/types/ObservableAPI.mustache
vendored
Normal file
67
modules/openapi-generator/src/main/resources/typescript/types/ObservableAPI.mustache
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
import { ResponseContext, RequestContext, HttpFile } from '../http/http';
|
||||
import * as models from '../models/all';
|
||||
import { Configuration} from '../configuration'
|
||||
import { Observable, of } from {{#useRxJS}}'rxjs'{{/useRxJS}}{{^useRxJS}}'../rxjsStub'{{/useRxJS}};
|
||||
import {mergeMap, map} from {{#useRxJS}}'rxjs/operators'{{/useRxJS}}{{^useRxJS}}'../rxjsStub'{{/useRxJS}};
|
||||
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
import { {{{ classname }}} } from '../models/{{{ classFilename }}}';
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
|
||||
{{#operations}}
|
||||
import { {{classname}}RequestFactory, {{classname}}ResponseProcessor} from "../apis/{{classname}}";
|
||||
export class Observable{{classname}} {
|
||||
private requestFactory: {{classname}}RequestFactory;
|
||||
private responseProcessor: {{classname}}ResponseProcessor;
|
||||
private configuration: Configuration;
|
||||
|
||||
public constructor(configuration: Configuration, requestFactory?: {{classname}}RequestFactory, responseProcessor?: {{classname}}ResponseProcessor) {
|
||||
this.configuration = configuration;
|
||||
this.requestFactory = requestFactory || new {{classname}}RequestFactory(configuration);
|
||||
this.responseProcessor = responseProcessor || new {{classname}}ResponseProcessor();
|
||||
}
|
||||
|
||||
{{#operation}}
|
||||
/**
|
||||
{{#notes}}
|
||||
* {{¬es}}
|
||||
{{/notes}}
|
||||
{{#summary}}
|
||||
* {{&summary}}
|
||||
{{/summary}}
|
||||
{{#allParams}}
|
||||
* @param {{paramName}} {{description}}
|
||||
{{/allParams}}
|
||||
*/
|
||||
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: Configuration): Observable<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}> {
|
||||
const requestContext = this.requestFactory.{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}options);
|
||||
|
||||
// build promise chain
|
||||
let middlewarePreObservable = of(requestContext);
|
||||
for (let middleware of this.configuration.middleware) {
|
||||
middlewarePreObservable = middlewarePreObservable.pipe(mergeMap((ctx: RequestContext) => middleware.pre(ctx)));
|
||||
}
|
||||
|
||||
return middlewarePreObservable.pipe(mergeMap((ctx: RequestContext) => this.configuration.httpApi.send(ctx))).
|
||||
pipe(mergeMap((response: ResponseContext) => {
|
||||
let middlewarePostObservable = of(response);
|
||||
for (let middleware of this.configuration.middleware) {
|
||||
middlewarePostObservable = middlewarePostObservable.pipe(mergeMap((rsp: ResponseContext) => middleware.post(rsp)));
|
||||
}
|
||||
return middlewarePostObservable.pipe(map((rsp: ResponseContext) => this.responseProcessor.{{nickname}}(rsp)));
|
||||
}));
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
|
||||
}
|
||||
|
||||
{{/operations}}
|
||||
|
||||
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
49
modules/openapi-generator/src/main/resources/typescript/types/PromiseAPI.mustache
vendored
Normal file
49
modules/openapi-generator/src/main/resources/typescript/types/PromiseAPI.mustache
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { ResponseContext, RequestContext, HttpFile } from '../http/http';
|
||||
import * as models from '../models/all';
|
||||
import { Configuration} from '../configuration'
|
||||
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
import { {{{ classname }}} } from '../models/{{{ classFilename }}}';
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
import { Observable{{classname}} } from './ObservableAPI';
|
||||
|
||||
|
||||
{{#operations}}
|
||||
import { {{classname}}RequestFactory, {{classname}}ResponseProcessor} from "../apis/{{classname}}";
|
||||
export class Promise{{classname}} {
|
||||
private api: Observable{{classname}}
|
||||
|
||||
public constructor(configuration: Configuration, requestFactory?: {{classname}}RequestFactory, responseProcessor?: {{classname}}ResponseProcessor) {
|
||||
this.api = new Observable{{classname}}(configuration, requestFactory, responseProcessor);
|
||||
}
|
||||
|
||||
{{#operation}}
|
||||
/**
|
||||
{{#notes}}
|
||||
* {{¬es}}
|
||||
{{/notes}}
|
||||
{{#summary}}
|
||||
* {{&summary}}
|
||||
{{/summary}}
|
||||
{{#allParams}}
|
||||
* @param {{paramName}} {{description}}
|
||||
{{/allParams}}
|
||||
*/
|
||||
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: Configuration): Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}> {
|
||||
const result = this.api.{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}options);
|
||||
return result.toPromise();
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
|
||||
}
|
||||
|
||||
{{/operations}}
|
||||
|
||||
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
28
modules/openapi-generator/src/main/resources/typescript/util.mustache
vendored
Normal file
28
modules/openapi-generator/src/main/resources/typescript/util.mustache
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Returns if a specific http code is in a given code range
|
||||
* where the code range is defined as a combination of digits
|
||||
* and "X" (the letter X) with a length of 3
|
||||
*
|
||||
* @param codeRange string with length 3 consisting of digits and "X" (the letter X)
|
||||
* @param code the http status code to be checked against the code range
|
||||
*/
|
||||
export function isCodeInRange(codeRange: string, code: number): boolean {
|
||||
// This is how the default value is encoded in OAG
|
||||
if (codeRange === "0") {
|
||||
return true;
|
||||
}
|
||||
if (codeRange == code.toString()) {
|
||||
return true;
|
||||
} else {
|
||||
const codeString = code.toString();
|
||||
if (codeString.length != codeRange.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < codeString.length; i++) {
|
||||
if (codeRange.charAt(i) != "X" && codeRange.charAt(i) != codeString.charAt(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -298,6 +298,7 @@ public class SpringCodegenTest {
|
||||
final String multipartMixedApi = files.get("/src/main/java/org/openapitools/api/MultipartMixedApi.java");
|
||||
Assert.assertTrue(multipartMixedApi.contains("MultipartFile file"));
|
||||
Assert.assertTrue(multipartMixedApi.contains("@RequestPart(value = \"file\", required = true)"));
|
||||
System.out.println(multipartMixedApi);
|
||||
Assert.assertTrue(multipartMixedApi.contains("@Valid @RequestPart(value = \"marker\", required = false)"));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
|
||||
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
version: 1.0.0
|
||||
title: Example
|
||||
license:
|
||||
name: MIT
|
||||
servers:
|
||||
- url: http://api.example.xyz/v1
|
||||
paths:
|
||||
/pets:
|
||||
patch:
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/Cat'
|
||||
- $ref: '#/components/schemas/Dog'
|
||||
# This field will not match to any type.
|
||||
- description: Any kind of pet
|
||||
discriminator:
|
||||
propertyName: pet_type
|
||||
responses:
|
||||
'200':
|
||||
description: Updated
|
||||
|
||||
/pets-filtered:
|
||||
patch:
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/PetByAge'
|
||||
- $ref: '#/components/schemas/PetByType'
|
||||
# This field will not match to any type.
|
||||
- description: Any kind of filter
|
||||
responses:
|
||||
'200':
|
||||
description: Updated
|
||||
|
||||
/file:
|
||||
post:
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
allOf:
|
||||
- type: file
|
||||
# This field will not match to any type.
|
||||
- description: The file to upload
|
||||
responses:
|
||||
'200':
|
||||
description: File uploaded
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Pet:
|
||||
type: object
|
||||
required:
|
||||
- pet_type
|
||||
Dog:
|
||||
allOf:
|
||||
# This field will not match to any type.
|
||||
- description: Dog information
|
||||
- $ref: '#/components/schemas/Pet'
|
||||
- type: object
|
||||
properties:
|
||||
bark:
|
||||
type: boolean
|
||||
breed:
|
||||
type: string
|
||||
enum: [Dingo, Husky, Retriever, Shepherd]
|
||||
Cat:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Pet'
|
||||
- type: object
|
||||
properties:
|
||||
hunts:
|
||||
type: boolean
|
||||
age:
|
||||
type: integer
|
||||
PetByAge:
|
||||
type: object
|
||||
properties:
|
||||
age:
|
||||
type: integer
|
||||
nickname:
|
||||
type: string
|
||||
required:
|
||||
- age
|
||||
|
||||
PetByType:
|
||||
type: object
|
||||
properties:
|
||||
pet_type:
|
||||
type: string
|
||||
enum: [Cat, Dog]
|
||||
hunts:
|
||||
type: boolean
|
||||
required:
|
||||
- pet_type
|
||||
28
pom.xml
28
pom.xml
@@ -991,6 +991,30 @@
|
||||
<module>samples/server/petstore/jaxrs-spec-interface-response</module>
|
||||
</modules>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>typescript-client-tests-default</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>env</name>
|
||||
<value>java</value>
|
||||
</property>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>samples/openapi3/client/petstore/typescript/tests/default</module>
|
||||
</modules>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>typescript-client-tests-jquery</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>env</name>
|
||||
<value>java</value>
|
||||
</property>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>samples/openapi3/client/petstore/typescript/tests/jquery</module>
|
||||
</modules>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>typescript-fetch-client-tests-default</id>
|
||||
<activation>
|
||||
@@ -1259,6 +1283,10 @@
|
||||
<module>samples/client/petstore/python-tornado</module>
|
||||
<module>samples/openapi3/client/petstore/python</module>
|
||||
<module>samples/openapi3/client/petstore/python-experimental</module>
|
||||
<module>samples/openapi3/client/petstore/typescript/builds/default</module>
|
||||
<module>samples/openapi3/client/petstore/typescript/tests/default</module>
|
||||
<module>samples/openapi3/client/petstore/typescript/builds/jquery</module>
|
||||
<module>samples/openapi3/client/petstore/typescript/tests/jquery</module>
|
||||
<module>samples/client/petstore/typescript-fetch/builds/default</module>
|
||||
<module>samples/client/petstore/typescript-fetch/builds/es6-target</module>
|
||||
<module>samples/client/petstore/typescript-fetch/builds/with-npm-version</module>
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
.Rbuildignore
|
||||
.gitignore
|
||||
.travis.yml
|
||||
DESCRIPTION
|
||||
NAMESPACE
|
||||
R/api_client.R
|
||||
R/api_response.R
|
||||
R/category.R
|
||||
R/model_api_response.R
|
||||
R/order.R
|
||||
R/pet.R
|
||||
R/pet_api.R
|
||||
R/store_api.R
|
||||
R/tag.R
|
||||
R/user.R
|
||||
R/user_api.R
|
||||
README.md
|
||||
docs/Category.md
|
||||
docs/ModelApiResponse.md
|
||||
docs/Order.md
|
||||
docs/Pet.md
|
||||
docs/PetApi.md
|
||||
docs/StoreApi.md
|
||||
docs/Tag.md
|
||||
docs/User.md
|
||||
docs/UserApi.md
|
||||
git_push.sh
|
||||
tests/testthat.R
|
||||
@@ -1,30 +0,0 @@
|
||||
README.md
|
||||
config/project-scratch-def.json
|
||||
force-app/main/default/classes/OAS.cls
|
||||
force-app/main/default/classes/OAS.cls-meta.xml
|
||||
force-app/main/default/classes/OASApiResponse.cls
|
||||
force-app/main/default/classes/OASApiResponse.cls-meta.xml
|
||||
force-app/main/default/classes/OASCategory.cls
|
||||
force-app/main/default/classes/OASCategory.cls-meta.xml
|
||||
force-app/main/default/classes/OASClient.cls
|
||||
force-app/main/default/classes/OASClient.cls-meta.xml
|
||||
force-app/main/default/classes/OASOrder.cls
|
||||
force-app/main/default/classes/OASOrder.cls-meta.xml
|
||||
force-app/main/default/classes/OASPet.cls
|
||||
force-app/main/default/classes/OASPet.cls-meta.xml
|
||||
force-app/main/default/classes/OASPetApi.cls
|
||||
force-app/main/default/classes/OASPetApi.cls-meta.xml
|
||||
force-app/main/default/classes/OASResponseMock.cls
|
||||
force-app/main/default/classes/OASResponseMock.cls-meta.xml
|
||||
force-app/main/default/classes/OASStoreApi.cls
|
||||
force-app/main/default/classes/OASStoreApi.cls-meta.xml
|
||||
force-app/main/default/classes/OASTag.cls
|
||||
force-app/main/default/classes/OASTag.cls-meta.xml
|
||||
force-app/main/default/classes/OASTest.cls
|
||||
force-app/main/default/classes/OASTest.cls-meta.xml
|
||||
force-app/main/default/classes/OASUser.cls
|
||||
force-app/main/default/classes/OASUser.cls-meta.xml
|
||||
force-app/main/default/classes/OASUserApi.cls
|
||||
force-app/main/default/classes/OASUserApi.cls-meta.xml
|
||||
force-app/main/default/namedCredentials/OpenAPI_Petstore.namedCredential-meta.xml
|
||||
sfdx-project.json
|
||||
@@ -1 +1 @@
|
||||
5.0.0-SNAPSHOT
|
||||
4.3.1-SNAPSHOT
|
||||
@@ -1,39 +0,0 @@
|
||||
.gitignore
|
||||
ApiClient.cpp
|
||||
ApiClient.h
|
||||
ApiConfiguration.cpp
|
||||
ApiConfiguration.h
|
||||
ApiException.cpp
|
||||
ApiException.h
|
||||
CMakeLists.txt
|
||||
HttpContent.cpp
|
||||
HttpContent.h
|
||||
IHttpBody.h
|
||||
JsonBody.cpp
|
||||
JsonBody.h
|
||||
ModelBase.cpp
|
||||
ModelBase.h
|
||||
MultipartFormData.cpp
|
||||
MultipartFormData.h
|
||||
Object.cpp
|
||||
Object.h
|
||||
README.md
|
||||
api/PetApi.cpp
|
||||
api/PetApi.h
|
||||
api/StoreApi.cpp
|
||||
api/StoreApi.h
|
||||
api/UserApi.cpp
|
||||
api/UserApi.h
|
||||
git_push.sh
|
||||
model/ApiResponse.cpp
|
||||
model/ApiResponse.h
|
||||
model/Category.cpp
|
||||
model/Category.h
|
||||
model/Order.cpp
|
||||
model/Order.h
|
||||
model/Pet.cpp
|
||||
model/Pet.h
|
||||
model/Tag.cpp
|
||||
model/Tag.h
|
||||
model/User.cpp
|
||||
model/User.h
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator
|
||||
* https://github.com/OpenAPITools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class OpenAPI : ModuleRules
|
||||
{
|
||||
public OpenAPI(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"Http",
|
||||
"Json",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user