Merge branch 'master' of https://github.com/swagger-api/swagger-codegen into feature/integration-test

This commit is contained in:
Kristof Vrolijkx 2016-05-16 13:47:22 +02:00
commit aa8b253e38
456 changed files with 10428 additions and 6696 deletions

12
.gitignore vendored
View File

@ -41,6 +41,7 @@ samples/server-generator/scalatra/target
samples/server-generator/scalatra/output/.history samples/server-generator/scalatra/output/.history
# nodejs # nodejs
**/node_modules/
samples/server-generator/node/output/node_modules samples/server-generator/node/output/node_modules
samples/server/petstore/nodejs/node_modules samples/server/petstore/nodejs/node_modules
samples/server/petstore/nodejs-server/node_modules samples/server/petstore/nodejs-server/node_modules
@ -116,13 +117,6 @@ samples/client/petstore/python/.venv/
# ts # ts
samples/client/petstore/typescript-node/npm/node_modules samples/client/petstore/typescript-node/npm/node_modules
samples/client/petstore/typescript-fetch/with-package-metadata/node_modules samples/client/petstore/typescript-fetch/**/dist/
samples/client/petstore/typescript-fetch/with-package-metadata/dist samples/client/petstore/typescript-fetch/**/typings
samples/client/petstore/typescript-fetch/with-package-metadata/typings
samples/client/petstore/typescript-fetch/default/node_modules
samples/client/petstore/typescript-fetch/default/dist
samples/client/petstore/typescript-fetch/default/typings
samples/client/petstore/typescript-fetch/default-es6/node_modules
samples/client/petstore/typescript-fetch/default-es6/dist
samples/client/petstore/typescript-fetch/default-es6/typings

View File

@ -608,7 +608,7 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
``` ```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \ -i http://petstore.swagger.io/v2/swagger.json \
-l silex \ -l silex-PHP \
-o samples/server/petstore/silex -o samples/server/petstore/silex
``` ```
@ -894,6 +894,7 @@ Here is a list of template creators:
* JAX-RS CXF: @hiveship * JAX-RS CXF: @hiveship
* PHP Lumen: @abcsum * PHP Lumen: @abcsum
* PHP Slim: @jfastnacht * PHP Slim: @jfastnacht
* Ruby on Rails 5: @zlx
## How to join the core team ## How to join the core team

View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn 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/swagger-codegen/src/main/resources/android -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l android -Dlibrary=httpclient -o samples/client/petstore/android/httpclient"
java $JAVA_OPTS -jar $executable $ags

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # 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" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/android -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l android -o samples/client/petstore/android/default" ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l android -o samples/client/petstore/android/volley"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

31
bin/rails5-petstore-server.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn 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/swagger-codegen/src/main/resources/rails5 -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l rails5 -o samples/server/petstore/rails5"
java $JAVA_OPTS -jar $executable $ags

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
./bin/typescript-fetch-petstore-target-es6.sh ./bin/typescript-fetch-petstore-target-es6.sh
./bin/typescript-fetch-petstore-target-with-package-metadata.sh ./bin/typescript-fetch-petstore-with-npm-version.sh
./bin/typescript-fetch-petstore.sh ./bin/typescript-fetch-petstore.sh

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # 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" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l typescript-fetch -c bin/typescript-fetch-petstore-target-es6.json -o samples/client/petstore/typescript-fetch/default-es6" ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l typescript-fetch -c bin/typescript-fetch-petstore-target-es6.json -o samples/client/petstore/typescript-fetch/builds/es6-target"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # 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" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l typescript-fetch -c bin/typescript-fetch-petstore-target-with-package-metadata.json -o samples/client/petstore/typescript-fetch/with-package-metadata" ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l typescript-fetch -c bin/typescript-fetch-petstore-with-npm-version.json -o samples/client/petstore/typescript-fetch/builds/with-npm-version"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # 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" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l typescript-fetch -o samples/client/petstore/typescript-fetch/default" ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l typescript-fetch -o samples/client/petstore/typescript-fetch/builds/default"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\rails5 -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l aspnet5 -o samples\server\petstore\rails5\
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -33,7 +33,7 @@ public class CodegenModel {
public Set<String> allMandatory; public Set<String> allMandatory;
public Set<String> imports = new TreeSet<String>(); public Set<String> imports = new TreeSet<String>();
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum; public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum, hasRequired;
public ExternalDocs externalDocs; public ExternalDocs externalDocs;
public Map<String, Object> vendorExtensions; public Map<String, Object> vendorExtensions;

View File

@ -7,13 +7,16 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Arrays;
public class CodegenOperation { public class CodegenOperation {
public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>(); public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>();
public Boolean hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams, public Boolean hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMapContainer, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMapContainer,
isListContainer, isMultipart, hasMore = Boolean.TRUE, isListContainer, isMultipart, hasMore = Boolean.TRUE,
isResponseBinary = Boolean.FALSE, hasReference = Boolean.FALSE; isResponseBinary = Boolean.FALSE, hasReference = Boolean.FALSE,
isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
isRestful;
public String path, operationId, returnType, httpMethod, returnBaseType, public String path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse, discriminator; returnContainer, summary, unescapedNotes, notes, baseName, defaultResponse, discriminator;
public List<Map<String, String>> consumes, produces; public List<Map<String, String>> consumes, produces;
@ -88,6 +91,81 @@ public class CodegenOperation {
return nonempty(formParams); return nonempty(formParams);
} }
/**
* Check if act as Restful index method
*
* @return true if act as Restful index method, false otherwise
*/
public boolean isRestfulIndex() {
return "GET".equals(httpMethod) && "".equals(pathWithoutBaseName());
}
/**
* Check if act as Restful show method
*
* @return true if act as Restful show method, false otherwise
*/
public boolean isRestfulShow() {
return "GET".equals(httpMethod) && isMemberPath();
}
/**
* Check if act as Restful create method
*
* @return true if act as Restful create method, false otherwise
*/
public boolean isRestfulCreate() {
return "POST".equals(httpMethod) && "".equals(pathWithoutBaseName());
}
/**
* Check if act as Restful update method
*
* @return true if act as Restful update method, false otherwise
*/
public boolean isRestfulUpdate() {
return Arrays.asList("PUT", "PATCH").contains(httpMethod) && isMemberPath();
}
/**
* Check if act as Restful destroy method
*
* @return true if act as Restful destroy method, false otherwise
*/
public boolean isRestfulDestroy() {
return "DELETE".equals(httpMethod) && isMemberPath();
}
/**
* Check if Restful-style
*
* @return true if Restful-style, false otherwise
*/
public boolean isRestful() {
return isRestfulIndex() || isRestfulShow() || isRestfulCreate() || isRestfulUpdate() || isRestfulDestroy();
}
/**
* Get the substring except baseName from path
*
* @return the substring
*/
private String pathWithoutBaseName() {
return baseName != null ? path.replace("/" + baseName.toLowerCase(), "") : path;
}
/**
* Check if the path match format /xxx/:id
*
* @return true if path act as member
*/
private boolean isMemberPath() {
if (pathParams.size() != 1) return false;
String id = pathParams.get(0).baseName;
return ("/{" + id + "}").equals(pathWithoutBaseName());
}
@Override @Override
public String toString() { public String toString() {
return String.format("%s(%s)", baseName, path); return String.format("%s(%s)", baseName, path);

View File

@ -1901,6 +1901,14 @@ public class DefaultCodegen {
} }
op.externalDocs = operation.getExternalDocs(); op.externalDocs = operation.getExternalDocs();
// set Restful Flag
op.isRestfulShow = op.isRestfulShow();
op.isRestfulIndex = op.isRestfulIndex();
op.isRestfulCreate = op.isRestfulCreate();
op.isRestfulUpdate = op.isRestfulUpdate();
op.isRestfulDestroy = op.isRestfulDestroy();
op.isRestful = op.isRestful();
return op; return op;
} }
@ -2519,6 +2527,7 @@ public class DefaultCodegen {
private void addVars(CodegenModel m, Map<String, Property> properties, List<String> required, private void addVars(CodegenModel m, Map<String, Property> properties, List<String> required,
Map<String, Property> allProperties, List<String> allRequired) { Map<String, Property> allProperties, List<String> allRequired) {
m.hasRequired = false;
if (properties != null && !properties.isEmpty()) { if (properties != null && !properties.isEmpty()) {
m.hasVars = true; m.hasVars = true;
m.hasEnums = false; m.hasEnums = false;
@ -2557,6 +2566,7 @@ public class DefaultCodegen {
} else { } else {
final CodegenProperty cp = fromProperty(key, prop); final CodegenProperty cp = fromProperty(key, prop);
cp.required = mandatory.contains(key) ? true : null; cp.required = mandatory.contains(key) ? true : null;
m.hasRequired = Boolean.TRUE.equals(m.hasRequired) || Boolean.TRUE.equals(cp.required);
if (cp.isEnum) { if (cp.isEnum) {
// FIXME: if supporting inheritance, when called a second time for allProperties it is possible for // FIXME: if supporting inheritance, when called a second time for allProperties it is possible for
// m.hasEnums to be set incorrectly if allProperties has enumerations but properties does not. // m.hasEnums to be set incorrectly if allProperties has enumerations but properties does not.

View File

@ -89,8 +89,8 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
cliOptions.add(CliOption.newBoolean(USE_ANDROID_MAVEN_GRADLE_PLUGIN, "A flag to toggle android-maven gradle plugin.") cliOptions.add(CliOption.newBoolean(USE_ANDROID_MAVEN_GRADLE_PLUGIN, "A flag to toggle android-maven gradle plugin.")
.defaultValue(Boolean.TRUE.toString())); .defaultValue(Boolean.TRUE.toString()));
supportedLibraries.put("<default>", "HTTP client: Apache HttpClient 4.3.6. JSON processing: Gson 2.3.1"); supportedLibraries.put("volley", "HTTP client: Volley 1.0.19 (default)");
supportedLibraries.put("volley", "HTTP client: Volley 1.0.19"); supportedLibraries.put("httpclient", "HTTP client: Apache HttpClient 4.3.6. JSON processing: Gson 2.3.1. IMPORTANT: Android client using HttpClient is not actively maintained and will be depecreated in the next major release.");
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use"); CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
library.setEnum(supportedLibraries); library.setEnum(supportedLibraries);
cliOptions.add(library); cliOptions.add(library);
@ -382,23 +382,26 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
additionalProperties.put( "modelDocPath", modelDocPath ); additionalProperties.put( "modelDocPath", modelDocPath );
if (StringUtils.isEmpty(getLibrary())) { if (StringUtils.isEmpty(getLibrary())) {
modelDocTemplateFiles.put( "model_doc.mustache", ".md" ); setLibrary("volley"); // set volley as the default library
apiDocTemplateFiles.put( "api_doc.mustache", ".md" );
//supportingFiles.add(new SupportingFile("api_doc.mustache", apiDocPath, "api.md"));
//supportingFiles.add(new SupportingFile("model_doc.mustache", modelDocPath, "model.md"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
addSupportingFilesForDefault();
} else if ("volley".equals(getLibrary())) {
modelDocTemplateFiles.put( "model_doc.mustache", ".md" );
apiDocTemplateFiles.put( "api_doc.mustache", ".md" );
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
//supportingFiles.add(new SupportingFile("api_doc.mustache", apiDocPath, "api.md"));
//supportingFiles.add(new SupportingFile("model_doc.mustache", modelDocPath, "model.md"));
addSupportingFilesForVolley();
} }
// determine which file (mustache) to add based on library
if ("volley".equals(getLibrary())) {
addSupportingFilesForVolley();
} else if ("httpclient".equals(getLibrary())) {
addSupportingFilesForHttpClient();
} else {
throw new IllegalArgumentException("Invalid 'library' option specified: '" + getLibrary() + "'. Must be 'httpclient' or 'volley' (default)");
}
} }
private void addSupportingFilesForDefault() { private void addSupportingFilesForHttpClient() {
// documentation files
modelDocTemplateFiles.put( "model_doc.mustache", ".md" );
apiDocTemplateFiles.put( "api_doc.mustache", ".md" );
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle")); supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle")); supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
@ -418,6 +421,13 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
} }
private void addSupportingFilesForVolley() { private void addSupportingFilesForVolley() {
// documentation files
modelDocTemplateFiles.put( "model_doc.mustache", ".md" );
apiDocTemplateFiles.put( "api_doc.mustache", ".md" );
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
// supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle")); // supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle")); supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));

View File

@ -218,6 +218,8 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
binRelativePath += "vendor"; binRelativePath += "vendor";
additionalProperties.put("binRelativePath", binRelativePath); additionalProperties.put("binRelativePath", binRelativePath);
supportingFiles.add(new SupportingFile("IApiAccessor.mustache",
clientPackageDir, "IApiAccessor.cs"));
supportingFiles.add(new SupportingFile("Configuration.mustache", supportingFiles.add(new SupportingFile("Configuration.mustache",
clientPackageDir, "Configuration.cs")); clientPackageDir, "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", supportingFiles.add(new SupportingFile("ApiClient.mustache",

View File

@ -107,12 +107,12 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(CliOption.newBoolean(USE_RX_JAVA, "Whether to use the RxJava adapter with the retrofit2 library.")); cliOptions.add(CliOption.newBoolean(USE_RX_JAVA, "Whether to use the RxJava adapter with the retrofit2 library."));
cliOptions.add(new CliOption("hideGenerationTimestamp", "hides the timestamp when files were generated")); cliOptions.add(new CliOption("hideGenerationTimestamp", "hides the timestamp when files were generated"));
supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2"); supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.19.1. JSON processing: Jackson 2.7.0");
supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.1.1"); supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.16.0. JSON processing: Jackson 2.7.0");
supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6"); supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.22.2. JSON processing: Jackson 2.7.0");
supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1"); supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.6.2");
supportedLibraries.put(RETROFIT_1, "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)"); supportedLibraries.put(RETROFIT_1, "HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)");
supportedLibraries.put(RETROFIT_2, "HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.1). Enable the RxJava adapter using '-DuseRxJava=true'. (RxJava 1.1.2)"); supportedLibraries.put(RETROFIT_2, "HTTP client: OkHttp 3.2.0. JSON processing: Gson 2.6.1 (Retrofit 2.0.2). Enable the RxJava adapter using '-DuseRxJava=true'. (RxJava 1.1.3)");
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use"); CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
library.setDefault(DEFAULT_LIBRARY); library.setDefault(DEFAULT_LIBRARY);

View File

@ -42,6 +42,9 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String[] specialWords = {"new", "copy"}; protected String[] specialWords = {"new", "copy"};
protected String apiDocPath = "docs/"; protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/"; protected String modelDocPath = "docs/";
protected String modelFilesPath = "Model/";
protected String coreFilesPath = "Core/";
protected String apiFilesPath = "Api/";
protected Set<String> advancedMapingTypes = new HashSet<String>(); protected Set<String> advancedMapingTypes = new HashSet<String>();
@ -223,35 +226,38 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
additionalProperties.put("apiDocPath", apiDocPath); additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath); additionalProperties.put("modelDocPath", modelDocPath);
String swaggerFolder = podName; additionalProperties.put("modelFilesPath", modelFilesPath);
additionalProperties.put("coreFilesPath", coreFilesPath);
additionalProperties.put("apiFilesPath", apiFilesPath);
modelPackage = swaggerFolder; modelPackage = podName;
apiPackage = swaggerFolder; apiPackage = podName;
supportingFiles.add(new SupportingFile("Object-header.mustache", swaggerFolder, classPrefix + "Object.h")); supportingFiles.add(new SupportingFile("Object-header.mustache", coreFileFolder(), classPrefix + "Object.h"));
supportingFiles.add(new SupportingFile("Object-body.mustache", swaggerFolder, classPrefix + "Object.m")); supportingFiles.add(new SupportingFile("Object-body.mustache", coreFileFolder(), classPrefix + "Object.m"));
supportingFiles.add(new SupportingFile("QueryParamCollection-header.mustache", swaggerFolder, classPrefix + "QueryParamCollection.h")); supportingFiles.add(new SupportingFile("QueryParamCollection-header.mustache", coreFileFolder(), classPrefix + "QueryParamCollection.h"));
supportingFiles.add(new SupportingFile("QueryParamCollection-body.mustache", swaggerFolder, classPrefix + "QueryParamCollection.m")); supportingFiles.add(new SupportingFile("QueryParamCollection-body.mustache", coreFileFolder(), classPrefix + "QueryParamCollection.m"));
supportingFiles.add(new SupportingFile("ApiClient-header.mustache", swaggerFolder, classPrefix + "ApiClient.h")); supportingFiles.add(new SupportingFile("ApiClient-header.mustache", coreFileFolder(), classPrefix + "ApiClient.h"));
supportingFiles.add(new SupportingFile("ApiClient-body.mustache", swaggerFolder, classPrefix + "ApiClient.m")); supportingFiles.add(new SupportingFile("ApiClient-body.mustache", coreFileFolder(), classPrefix + "ApiClient.m"));
supportingFiles.add(new SupportingFile("JSONResponseSerializer-header.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.h")); supportingFiles.add(new SupportingFile("JSONResponseSerializer-header.mustache", coreFileFolder(), classPrefix + "JSONResponseSerializer.h"));
supportingFiles.add(new SupportingFile("JSONResponseSerializer-body.mustache", swaggerFolder, classPrefix + "JSONResponseSerializer.m")); supportingFiles.add(new SupportingFile("JSONResponseSerializer-body.mustache", coreFileFolder(), classPrefix + "JSONResponseSerializer.m"));
supportingFiles.add(new SupportingFile("JSONRequestSerializer-body.mustache", swaggerFolder, classPrefix + "JSONRequestSerializer.m")); supportingFiles.add(new SupportingFile("JSONRequestSerializer-body.mustache", coreFileFolder(), classPrefix + "JSONRequestSerializer.m"));
supportingFiles.add(new SupportingFile("JSONRequestSerializer-header.mustache", swaggerFolder, classPrefix + "JSONRequestSerializer.h")); supportingFiles.add(new SupportingFile("JSONRequestSerializer-header.mustache", coreFileFolder(), classPrefix + "JSONRequestSerializer.h"));
supportingFiles.add(new SupportingFile("ResponseDeserializer-body.mustache", swaggerFolder, classPrefix + "ResponseDeserializer.m")); supportingFiles.add(new SupportingFile("ResponseDeserializer-body.mustache", coreFileFolder(), classPrefix + "ResponseDeserializer.m"));
supportingFiles.add(new SupportingFile("ResponseDeserializer-header.mustache", swaggerFolder, classPrefix + "ResponseDeserializer.h")); supportingFiles.add(new SupportingFile("ResponseDeserializer-header.mustache", coreFileFolder(), classPrefix + "ResponseDeserializer.h"));
supportingFiles.add(new SupportingFile("Sanitizer-body.mustache", swaggerFolder, classPrefix + "Sanitizer.m")); supportingFiles.add(new SupportingFile("Sanitizer-body.mustache", coreFileFolder(), classPrefix + "Sanitizer.m"));
supportingFiles.add(new SupportingFile("Sanitizer-header.mustache", swaggerFolder, classPrefix + "Sanitizer.h")); supportingFiles.add(new SupportingFile("Sanitizer-header.mustache", coreFileFolder(), classPrefix + "Sanitizer.h"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", swaggerFolder, "JSONValueTransformer+ISO8601.m")); supportingFiles.add(new SupportingFile("Logger-body.mustache", coreFileFolder(), classPrefix + "Logger.m"));
supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", swaggerFolder, "JSONValueTransformer+ISO8601.h")); supportingFiles.add(new SupportingFile("Logger-header.mustache", coreFileFolder(), classPrefix + "Logger.h"));
supportingFiles.add(new SupportingFile("Configuration-body.mustache", swaggerFolder, classPrefix + "Configuration.m")); supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.m", coreFileFolder(), "JSONValueTransformer+ISO8601.m"));
supportingFiles.add(new SupportingFile("Configuration-header.mustache", swaggerFolder, classPrefix + "Configuration.h")); supportingFiles.add(new SupportingFile("JSONValueTransformer+ISO8601.h", coreFileFolder(), "JSONValueTransformer+ISO8601.h"));
supportingFiles.add(new SupportingFile("Configuration-body.mustache", coreFileFolder(), classPrefix + "Configuration.m"));
supportingFiles.add(new SupportingFile("Configuration-header.mustache", coreFileFolder(), classPrefix + "Configuration.h"));
supportingFiles.add(new SupportingFile("podspec.mustache", "", podName + ".podspec")); supportingFiles.add(new SupportingFile("podspec.mustache", "", podName + ".podspec"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh")); supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore")); supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
} }
@Override @Override
@ -454,12 +460,16 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return outputFolder + File.separatorChar + apiPackage(); return (outputFolder + "/"+ apiPackage() + "/" + apiFilesPath).replace("/", File.separator);
} }
@Override @Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + File.separatorChar + modelPackage(); return (outputFolder + "/"+ modelPackage() + "/" + modelFilesPath).replace("/", File.separator);
}
public String coreFileFolder() {
return (apiPackage() + "/" + coreFilesPath).replace("/", File.separator);
} }
@Override @Override

View File

@ -3,6 +3,7 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenParameter; import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenProperty; import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
@ -13,6 +14,7 @@ import io.swagger.models.properties.*;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashSet; import java.util.HashSet;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -35,7 +37,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String composerVendorName = "swagger"; protected String composerVendorName = "swagger";
protected String composerProjectName = "swagger-client"; protected String composerProjectName = "swagger-client";
protected String packagePath = "SwaggerClient-php"; protected String packagePath = "SwaggerClient-php";
protected String artifactVersion = "1.0.0"; protected String artifactVersion = null;
protected String srcBasePath = "lib"; protected String srcBasePath = "lib";
protected String testBasePath = "test"; protected String testBasePath = "test";
protected String docsBasePath = "docs"; protected String docsBasePath = "docs";
@ -626,4 +628,14 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
// process enum in models // process enum in models
return postProcessModelsEnum(objs); return postProcessModelsEnum(objs);
} }
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation op : operationList) {
op.vendorExtensions.put("x-testOperationId", camelize(op.operationId));
}
return objs;
}
} }

View File

@ -0,0 +1,323 @@
package io.swagger.codegen.languages;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Rails5ServerCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(Rails5ServerCodegen.class);
protected String gemName;
protected String moduleName;
protected String gemVersion = "1.0.0";
protected String appFolder = "app";
protected String channelsFolder = appFolder + File.separator + "channels";
protected String applicationCableFolder = channelsFolder + File.separator + "application_cable";
protected String controllersFolder = appFolder + File.separator + "controllers";
protected String jobsFolder = appFolder + File.separator + "jobs";
protected String mailersFolder = appFolder + File.separator + "mailers";
protected String modelsFolder = appFolder + File.separator + "models";
protected String viewsFolder = appFolder + File.separator + "views";
protected String layoutsFolder = viewsFolder + File.separator + "layouts";
protected String binFolder = "bin";
protected String configFolder = "config";
protected String environmentsFolder = configFolder + File.separator + "config";
protected String initializersFolder = configFolder + File.separator + "initializers";
protected String localesFolder = configFolder + File.separator + "locales";
protected String dbFolder = "db";
protected String migrateFolder = dbFolder + File.separator + "migrate";
protected String libFolder = "lib";
protected String tasksFolder = libFolder + File.separator + "tasks";
protected String logFolder = "log";
protected String publicFolder = "public";
protected String testFolder = "test";
protected String tmpFolder = "tmp";
protected String cacheFolder = tmpFolder + File.separator + "cache";
protected String pidFolder = tmpFolder + File.separator + "pids";
protected String socketsFolder = tmpFolder + File.separator + "sockets";
protected String vendorFolder = "vendor";
public Rails5ServerCodegen() {
super();
apiPackage = "app/controllers";
outputFolder = "generated-code" + File.separator + "rails5";
// no model
modelTemplateFiles.clear();
apiTemplateFiles.put("controller.mustache", ".rb");
embeddedTemplateDir = templateDir = "rails5";
typeMapping.clear();
languageSpecificPrimitives.clear();
setReservedWordsLowerCase(
Arrays.asList(
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN",
"break", "do", "false", "next", "rescue", "then", "when", "END", "case",
"else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif",
"if", "not", "return", "undef", "yield")
);
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("array");
languageSpecificPrimitives.add("map");
languageSpecificPrimitives.add("string");
languageSpecificPrimitives.add("DateTime");
typeMapping.put("long", "int");
typeMapping.put("integer", "int");
typeMapping.put("Array", "array");
typeMapping.put("String", "string");
typeMapping.put("List", "array");
typeMapping.put("map", "map");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
// remove modelPackage and apiPackage added by default
cliOptions.clear();
}
@Override
public void processOpts() {
super.processOpts();
// use constant model/api package (folder path)
//setModelPackage("models");
setApiPackage("app/controllers");
supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("Rakefile", "", "Rakefile"));
supportingFiles.add(new SupportingFile("config.ru", "", "config.ru"));
supportingFiles.add(new SupportingFile("channel.rb", applicationCableFolder, "channel.rb"));
supportingFiles.add(new SupportingFile("connection.rb", applicationCableFolder, "connection.rb"));
supportingFiles.add(new SupportingFile("application_controller.rb", controllersFolder, "application_controller.rb"));
supportingFiles.add(new SupportingFile("application_job.rb", jobsFolder, "application_job.rb"));
supportingFiles.add(new SupportingFile("application_mailer.rb", mailersFolder, "application_mailer.rb"));
supportingFiles.add(new SupportingFile("application_record.rb", modelsFolder, "application_record.rb"));
supportingFiles.add(new SupportingFile("mailer.html.erb", layoutsFolder, "mailer.html.erb"));
supportingFiles.add(new SupportingFile("mailer.text.erb", layoutsFolder, "mailer.text.erb"));
supportingFiles.add(new SupportingFile("bundle", binFolder, "bundle"));
supportingFiles.add(new SupportingFile("rails", binFolder, "rails"));
supportingFiles.add(new SupportingFile("rake", binFolder, "rake"));
supportingFiles.add(new SupportingFile("setup", binFolder, "setup"));
supportingFiles.add(new SupportingFile("update", binFolder, "update"));
supportingFiles.add(new SupportingFile("development.rb", environmentsFolder, "development.rb"));
supportingFiles.add(new SupportingFile("production.rb", environmentsFolder, "production.rb"));
supportingFiles.add(new SupportingFile("active_record_belongs_to_required_by_default.rb", initializersFolder, "active_record_belongs_to_required_by_default.rb"));
supportingFiles.add(new SupportingFile("application_controller_renderer.rb", initializersFolder, "application_controller_renderer.rb"));
supportingFiles.add(new SupportingFile("backtrace_silencers.rb", initializersFolder, "backtrace_silencers.rb"));
supportingFiles.add(new SupportingFile("callback_terminator.rb", initializersFolder, "callback_terminator.rb"));
supportingFiles.add(new SupportingFile("cors.rb", initializersFolder, "cors.rb"));
supportingFiles.add(new SupportingFile("filter_parameter_logging.rb", initializersFolder, "filter_parameter_logging.rb"));
supportingFiles.add(new SupportingFile("inflections.rb", initializersFolder, "inflections.rb"));
supportingFiles.add(new SupportingFile("mime_types.rb", initializersFolder, "mime_types.rb"));
supportingFiles.add(new SupportingFile("ssl_options.rb", initializersFolder, "ssl_options.rb"));
supportingFiles.add(new SupportingFile("to_time_preserves_timezone.rb", initializersFolder, "to_time_preserves_timezone.rb"));
supportingFiles.add(new SupportingFile("en.yml", localesFolder, "en.yml"));
supportingFiles.add(new SupportingFile("application.rb", configFolder, "application.rb"));
supportingFiles.add(new SupportingFile("boot.rb", configFolder, "boot.rb"));
supportingFiles.add(new SupportingFile("cable.yml", configFolder, "cable.yml"));
supportingFiles.add(new SupportingFile("database.yml", configFolder, "database.yml"));
supportingFiles.add(new SupportingFile("environment.rb", configFolder, "environment.rb"));
supportingFiles.add(new SupportingFile("puma.rb", configFolder, "puma.rb"));
supportingFiles.add(new SupportingFile("routes.mustache", configFolder, "routes.rb"));
supportingFiles.add(new SupportingFile("secrets.yml", configFolder, "secrets.yml"));
supportingFiles.add(new SupportingFile("spring.rb", configFolder, "spring.rb"));
supportingFiles.add(new SupportingFile(".keep", migrateFolder, ".keep"));
supportingFiles.add(new SupportingFile("schema.rb", dbFolder, "schema.rb"));
supportingFiles.add(new SupportingFile("seeds.rb", dbFolder, "seeds.rb"));
supportingFiles.add(new SupportingFile(".keep", tasksFolder, ".keep"));
supportingFiles.add(new SupportingFile(".keep", logFolder, ".keep"));
supportingFiles.add(new SupportingFile("404.html", publicFolder, "404.html"));
supportingFiles.add(new SupportingFile("422.html", publicFolder, "422.html"));
supportingFiles.add(new SupportingFile("500.html", publicFolder, "500.html"));
supportingFiles.add(new SupportingFile("apple-touch-icon-precomposed.png", publicFolder, "apple-touch-icon-precomposed.png"));
supportingFiles.add(new SupportingFile("apple-touch-icon.png", publicFolder, "apple-touch-icon.png"));
supportingFiles.add(new SupportingFile("favicon.ico", publicFolder, "favicon.ico"));
supportingFiles.add(new SupportingFile("robots.txt", publicFolder, "robots.txt"));
supportingFiles.add(new SupportingFile("robots.txt", publicFolder, "robots.txt"));
supportingFiles.add(new SupportingFile("test_helper.rb", testFolder, "test_helper.rb"));
supportingFiles.add(new SupportingFile(".keep", cacheFolder, ".keep"));
supportingFiles.add(new SupportingFile(".keep", pidFolder, ".keep"));
supportingFiles.add(new SupportingFile(".keep", socketsFolder, ".keep"));
supportingFiles.add(new SupportingFile("restart.txt", tmpFolder, "restart.txt"));
supportingFiles.add(new SupportingFile(".keep", vendorFolder, ".keep"));
}
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "rails5";
}
@Override
public String getHelp() {
return "Generates a Rails5 server library.";
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + apiPackage.replace("/", File.separator);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = swaggerType;
}
if (type == null) {
return null;
}
return type;
}
@Override
public String toDefaultValue(Property p) {
return "null";
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // 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();
}
// camelize (lower first character) the variable name
// petId => pet_id
name = underscore(name);
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// underscore the model file name
// PhoneNumber.rb => phone_number.rb
return underscore(name);
}
@Override
public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PhoneNumberApi.rb => phone_number_api.rb
return underscore(name) + "_controllers";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "ApiController";
}
// e.g. phone_number_api => PhoneNumberApi
return camelize(name) + "Controller";
}
@Override
public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
}
return underscore(operationId);
}
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) {
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
LOGGER.error(e.getMessage(), e);
}
}
return super.postProcessSupportingFileData(objs);
}
}

View File

@ -355,8 +355,8 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
if (value.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) { if (value.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) {
return value; return value;
} }
char[] separators = {'-', '_', ' '}; char[] separators = {'-', '_', ' ', ':'};
return WordUtils.capitalizeFully(StringUtils.lowerCase(value), separators).replaceAll("[-_ ]", ""); return WordUtils.capitalizeFully(StringUtils.lowerCase(value), separators).replaceAll("[-_ :]", "");
} }
@ -502,6 +502,7 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toEnumVarName(String name, String datatype) { public String toEnumVarName(String name, String datatype) {
// TODO: this code is probably useless, because the var name is computed from the value in map.put("enum", toSwiftyEnumName(value));
// number // number
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) { if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
String varName = new String(name); String varName = new String(name);
@ -525,8 +526,9 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toEnumName(CodegenProperty property) { public String toEnumName(CodegenProperty property) {
String enumName = underscore(toModelName(property.name)).toUpperCase(); String enumName = toModelName(property.name);
// TODO: toModelName already does something for names starting with number, so this code is probably never called
if (enumName.matches("\\d.*")) { // starts with number if (enumName.matches("\\d.*")) { // starts with number
return "_" + enumName; return "_" + enumName;
} else { } else {

View File

@ -26,7 +26,6 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
super.processOpts(); super.processOpts();
supportingFiles.add(new SupportingFile("api.mustache", "", "api.ts")); supportingFiles.add(new SupportingFile("api.mustache", "", "api.ts"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh")); supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("assign.ts", "", "assign.ts"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md")); supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("package.json.mustache", "", "package.json")); supportingFiles.add(new SupportingFile("package.json.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("typings.json.mustache", "", "typings.json")); supportingFiles.add(new SupportingFile("typings.json.mustache", "", "typings.json"));

View File

@ -23,14 +23,17 @@ import feign.Request.Options;
import feign.RequestInterceptor; import feign.RequestInterceptor;
import feign.RequestTemplate; import feign.RequestTemplate;
import feign.Response; import feign.Response;
import feign.RetryableException;
import feign.Util; import feign.Util;
import {{invokerPackage}}.StringUtil; import {{invokerPackage}}.StringUtil;
public class OAuth implements RequestInterceptor { public class OAuth implements RequestInterceptor {
static final int MILLIS_PER_SECOND = 1000;
public interface AccessTokenListener { public interface AccessTokenListener {
public void notify(BasicOAuthToken token); void notify(BasicOAuthToken token);
} }
private volatile String accessToken; private volatile String accessToken;
@ -41,21 +44,13 @@ public class OAuth implements RequestInterceptor {
private AccessTokenListener accessTokenListener; private AccessTokenListener accessTokenListener;
public OAuth(Client client, TokenRequestBuilder requestBuilder) { public OAuth(Client client, TokenRequestBuilder requestBuilder) {
setOauthClient(client); this.oauthClient = new OAuthClient(new OAuthFeignClient(client));
this.tokenRequestBuilder = requestBuilder; this.tokenRequestBuilder = requestBuilder;
} }
public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes));
setFlow(flow);
authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl);
}
public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes);
}
public void setFlow(OAuthFlow flow) {
switch(flow) { switch(flow) {
case accessCode: case accessCode:
case implicit: case implicit:
@ -70,6 +65,11 @@ public class OAuth implements RequestInterceptor {
default: default:
break; break;
} }
authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl);
}
public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes);
} }
@Override @Override
@ -80,34 +80,29 @@ public class OAuth implements RequestInterceptor {
} }
// If first time, get the token // If first time, get the token
if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) {
try { updateAccessToken();
updateAccessToken();
} catch (OAuthSystemException e) {
e.printStackTrace();
return;
} catch (OAuthProblemException e) {
e.printStackTrace();
return;
}
} }
if (getAccessToken() != null) { if (getAccessToken() != null) {
template.header("Authorization", "Bearer " + getAccessToken()); template.header("Authorization", "Bearer " + getAccessToken());
} }
} }
public synchronized void updateAccessToken() throws OAuthSystemException, OAuthProblemException { public synchronized void updateAccessToken() {
if (getAccessToken() == null) { OAuthJSONAccessTokenResponse accessTokenResponse;
OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); try {
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); } catch (Exception e) {
if (accessTokenListener != null) { throw new RetryableException(e.getMessage(), e,null);
accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); }
} if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn());
if (accessTokenListener != null) {
accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken());
} }
} }
} }
public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
this.accessTokenListener = accessTokenListener; this.accessTokenListener = accessTokenListener;
} }
@ -117,7 +112,7 @@ public class OAuth implements RequestInterceptor {
public synchronized void setAccessToken(String accessToken, Long expiresIn) { public synchronized void setAccessToken(String accessToken, Long expiresIn) {
this.accessToken = accessToken; this.accessToken = accessToken;
this.expirationTimeMillis = System.currentTimeMillis() + expiresIn * 1000; this.expirationTimeMillis = System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND;
} }
public TokenRequestBuilder getTokenRequestBuilder() { public TokenRequestBuilder getTokenRequestBuilder() {
@ -148,7 +143,7 @@ public class OAuth implements RequestInterceptor {
this.oauthClient = new OAuthClient( new OAuthFeignClient(client)); this.oauthClient = new OAuthClient( new OAuthFeignClient(client));
} }
public class OAuthFeignClient implements HttpClient { public static class OAuthFeignClient implements HttpClient {
private Client client; private Client client;
@ -198,6 +193,5 @@ public class OAuth implements RequestInterceptor {
public void shutdown() { public void shutdown() {
// Nothing to do here // Nothing to do here
} }
} }
} }

View File

@ -163,10 +163,9 @@
<jetty-version>9.2.9.v20150224</jetty-version> <jetty-version>9.2.9.v20150224</jetty-version>
<jersey-version>1.13</jersey-version> <jersey-version>1.13</jersey-version>
<slf4j-version>1.6.3</slf4j-version> <slf4j-version>1.6.3</slf4j-version>
<scala-test-version>1.6.1</scala-test-version>
<junit-version>4.8.1</junit-version> <junit-version>4.8.1</junit-version>
<servlet-api-version>2.5</servlet-api-version> <servlet-api-version>2.5</servlet-api-version>
<springfox-version>2.0.4-SNAPSHOT</springfox-version> <springfox-version>2.4.0</springfox-version>
<spring-version>4.0.9.RELEASE</spring-version> <spring-version>4.2.5.RELEASE</spring-version>
</properties> </properties>
</project> </project>

View File

@ -27,6 +27,7 @@ io.swagger.codegen.languages.ScalaClientCodegen
io.swagger.codegen.languages.ScalatraServerCodegen io.swagger.codegen.languages.ScalatraServerCodegen
io.swagger.codegen.languages.SilexServerCodegen io.swagger.codegen.languages.SilexServerCodegen
io.swagger.codegen.languages.SinatraServerCodegen io.swagger.codegen.languages.SinatraServerCodegen
io.swagger.codegen.languages.Rails5ServerCodegen
io.swagger.codegen.languages.SlimFrameworkServerCodegen io.swagger.codegen.languages.SlimFrameworkServerCodegen
io.swagger.codegen.languages.SpringBootServerCodegen io.swagger.codegen.languages.SpringBootServerCodegen
io.swagger.codegen.languages.SpringMVCServerCodegen io.swagger.codegen.languages.SpringMVCServerCodegen

View File

@ -1,44 +1,54 @@
# TypeScript-Fetch # TypeScript-Fetch
This generator creates TypeScript/JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The codegen Node module can be used in the following environments: This generator creates TypeScript/JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The generated Node module can be used in the following environments:
* Node.JS Environment
* Node.js
* Webpack * Webpack
* Browserify * Browserify
It is usable in both TypeScript and JavaScript. In TypeScript, the definition should be automatically resolved via `typings` in `package.json`. ([Reference](http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html)) Language level
* ES5 - you must have a Promises/A+ library installed
* ES6
Module system
* CommonJS
* ES6 module system
It can be used in both TypeScript and JavaScript. In TypeScript, the definition should be automatically resolved via `package.json`. ([Reference](http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html))
### Installation ### ### Installation ###
`swagger-codegen` does not generate JavaScript directly. The codegen Node module comes with `package.json` that bundles `typescript` and `typings` so it can self-compile. The self-compile is normally run automatically via the `npm` `postinstall` script of `npm install`. `swagger-codegen` does not generate JavaScript directly. The generated Node module comes with `package.json` that bundles `typescript` and `typings` so it can self-compile during `prepublish` stage. The should be run automatically during `npm install` or `npm publish`.
CAVEAT: Due to [privilege implications](https://docs.npmjs.com/misc/scripts#user), `npm` may skip `postinstall` script if the user is `root`. You would need to manually invoke `npm install` or `npm run postinstall` for the codegen module if that's the case. CAVEAT: Due to [privilege implications](https://docs.npmjs.com/misc/scripts#user), `npm` would skip all scripts if the user is `root`. You would need to manually run it with `npm run prepublish` or run `npm install --unsafe-perm`.
#### NPM repository ### #### NPM ####
If you remove `"private": true` from `package.json`, you may publish the module to NPM. In which case, you would be able to install the module as any other NPM module. You may publish the module to NPM. In this case, you would be able to install the module as any other NPM module. It maybe useful to use [scoped packages](https://docs.npmjs.com/misc/scope).
It maybe useful to use [scoped packages](https://docs.npmjs.com/misc/scope). You can also use `npm link` to link the module. However, this would not modify `package.json` of the installing project, as such you would need to relink everytime you deploy that project.
#### NPM install local file ### You can also directly install the module using `npm install file_path`. If you do `npm install file_path --save`, NPM will save relative path to `package.json`. In this case, `npm install` and `npm shrinkwrap` may misbehave. You would need to manually edit `package.json` and replace it with absolute path.
You should be able to directly install the module using `npm install file:///codegen_path`.
NOTES: If you do `npm install file:///codegen_path --save` NPM might convert your path to relative path, maybe have adverse affect. `npm install` and `npm shrinkwrap` may misbehave if the installation path is not absolute. Regardless of which method you deployed your NPM module, the ES6 module syntaxes are as follows:
#### direct copy/symlink ###
You may also simply copy or symlink the codegen into a directly under your project. The syntax of the usage would differ if you take this route. (See below)
### Usage ###
With ES6 module syntax, the following syntaxes are supported:
``` ```
import * as localName from 'npmName'; import * as localName from 'npmName';
import {operationId} from 'npmName'; import {operationId} from 'npmName';
```
The CommonJS syntax is as follows:
```
import localName = require('npmName');
```
#### Direct copy/symlink ####
You may also simply copy or symlink the generated module into a directory under your project. The syntax of this is as follows:
With ES6 module syntax, the following syntaxes are supported:
```
import * as localName from './symlinkDir'; import * as localName from './symlinkDir';
import {operationId} from './symlinkDir'; import {operationId} from './symlinkDir';
``` ```
With CommonJS, the following syntaxes are supported: The CommonJS syntax is as follows:
``` ```
import localName = require('npmName');
import localName = require('./symlinkDir')'; import localName = require('./symlinkDir')';
``` ```

View File

@ -1,7 +1,30 @@
import * as querystring from 'querystring'; import * as querystring from "querystring";
import * as fetch from 'isomorphic-fetch'; import * as url from "url";
import {assign} from './assign';
import * as isomorphicFetch from "isomorphic-fetch";
{{^supportsES6}}
import * as assign from "core-js/library/fn/object/assign";
{{/supportsES6}}
interface Dictionary<T> { [index: string]: T; }
export interface FetchAPI { (url: string, init?: any): Promise<any>; }
const BASE_PATH = "{{basePath}}";
export interface FetchArgs {
url: string;
options: any;
}
export class BaseAPI {
basePath: string;
fetch: FetchAPI;
constructor(fetch: FetchAPI = isomorphicFetch, basePath: string = BASE_PATH) {
this.basePath = basePath;
this.fetch = fetch;
}
}
{{#models}} {{#models}}
{{#model}} {{#model}}
@ -13,24 +36,20 @@ import {assign} from './assign';
export interface {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{ export interface {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{
{{#vars}} {{#vars}}
{{#description}} {{#description}}
/** /**
* {{{description}}} * {{{description}}}
*/ */
{{/description}} {{/description}}
"{{name}}"{{^required}}?{{/required}}: {{#isEnum}}{{classname}}.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}}; "{{name}}"{{^required}}?{{/required}}: {{#isEnum}}{{classname}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}};
{{/vars}} {{/vars}}
} }
{{#hasEnums}} {{#hasEnums}}
export namespace {{classname}} {
{{#vars}} {{#vars}}
{{#isEnum}} {{#isEnum}}
export type {{classname}}{{datatypeWithEnum}} = {{#allowableValues}}{{#values}}"{{.}}"{{^-last}} | {{/-last}}{{/values}}{{/allowableValues}};
export type {{datatypeWithEnum}} = {{#allowableValues}}{{#values}}'{{.}}'{{^-last}} | {{/-last}}{{/values}}{{/allowableValues}};
{{/isEnum}} {{/isEnum}}
{{/vars}} {{/vars}}
}
{{/hasEnums}} {{/hasEnums}}
{{/model}} {{/model}}
{{/models}} {{/models}}
@ -38,96 +57,111 @@ export type {{datatypeWithEnum}} = {{#allowableValues}}{{#values}}'{{.}}'{{^-las
{{#apiInfo}} {{#apiInfo}}
{{#apis}} {{#apis}}
{{#operations}} {{#operations}}
//export namespace {{package}} {
'use strict';
{{#description}}
/**
* {{&description}}
*/
{{/description}}
export class {{classname}} {
protected basePath = '{{basePath}}';
public defaultHeaders : any = {};
constructor(basePath?: string) {
if (basePath) {
this.basePath = basePath;
}
}
/**
* {{classname}} - fetch parameter creator{{#description}}
* {{&description}}{{/description}}
*/
export const {{classname}}FetchParamCreactor = {
{{#operation}} {{#operation}}
/** /** {{#summary}}
* {{summary}} * {{summary}}{{/summary}}{{#notes}}
* {{notes}} * {{notes}}{{/notes}}{{#allParams}}
{{#allParams}}* @param {{paramName}} {{description}} * @param {{paramName}} {{description}}{{/allParams}}
{{/allParams}}*/ */
public {{nickname}} (params: { {{#allParams}} {{paramName}}{{^required}}?{{/required}}: {{{dataType}}};{{/allParams}} }, extraQueryParams?: any, extraFetchParams?: any ) : Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> { {{nickname}}({{#hasParams}}params: { {{#allParams}} {{paramName}}{{^required}}?{{/required}}: {{{dataType}}};{{/allParams}} }{{/hasParams}}): FetchArgs {
const localVarPath = this.basePath + '{{path}}'{{#pathParams}}
.replace('{' + '{{baseName}}' + '}', String(params.{{paramName}})){{/pathParams}};
let queryParameters: any = assign({}, extraQueryParams);
let headerParams: any = assign({}, this.defaultHeaders);
{{#hasFormParams}}
let formParams: any = {};
headerParams['Content-Type'] = 'application/x-www-form-urlencoded';
{{/hasFormParams}}
{{#hasBodyParam}}
headerParams['Content-Type'] = 'application/json';
{{/hasBodyParam}}
{{#allParams}} {{#allParams}}
{{#required}} {{#required}}
// verify required parameter '{{paramName}}' is set // verify required parameter "{{paramName}}" is set
if (params.{{paramName}} == null) { if (params["{{paramName}}"] == null) {
throw new Error('Missing required parameter {{paramName}} when calling {{nickname}}'); throw new Error("Missing required parameter {{paramName}} when calling {{nickname}}");
} }
{{/required}} {{/required}}
{{/allParams}} {{/allParams}}
{{#queryParams}} const baseUrl = `{{path}}`{{#pathParams}}
if (params.{{paramName}} !== undefined) { .replace(`{${"{{baseName}}"}}`, `${ params.{{paramName}} }`){{/pathParams}};
queryParameters['{{baseName}}'] = params.{{paramName}}; let urlObj = url.parse(baseUrl, true);
} {{#hasQueryParams}}
urlObj.query = {{#supportsES6}}Object.{{/supportsES6}}assign({}, urlObj.query, { {{#queryParams}}
"{{baseName}}": params.{{paramName}},{{/queryParams}}
});
{{/hasQueryParams}}
let fetchOptions: RequestInit = { method: "{{httpMethod}}" };
{{/queryParams}} let contentTypeHeader: Dictionary<string>;
{{#headerParams}} {{#hasFormParams}}
headerParams['{{baseName}}'] = params.{{paramName}}; contentTypeHeader = { "Content-Type": "application/x-www-form-urlencoded" };
fetchOptions.body = querystring.stringify({ {{#formParams}}
"{{baseName}}": params.{{paramName}},{{/formParams}}
});
{{/hasFormParams}}
{{#hasBodyParam}}
contentTypeHeader = { "Content-Type": "application/json" };{{#bodyParam}}
if (params["{{paramName}}"]) {
fetchOptions.body = JSON.stringify(params["{{paramName}}"] || {});
}{{/bodyParam}}
{{/hasBodyParam}}
{{#hasHeaderParam}}
fetchOptions.headers = {{#supportsES6}}Object.{{/supportsES6}}assign({ {{#headerParams}}
"{{baseName}}": params.{{paramName}},{{/headerParams}}
}, contentTypeHeader);
{{/hasHeaderParam}}
{{^hasHeaderParam}}
if (contentTypeHeader) {
fetchOptions.headers = contentTypeHeader;
}
{{/hasHeaderParam}}
return {
url: url.format(urlObj),
options: fetchOptions,
};
},
{{/operation}}
}
{{/headerParams}} /**
{{#formParams}} * {{classname}} - functional programming interface{{#description}}
formParams['{{baseName}}'] = params.{{paramName}}; * {{&description}}{{/description}}
*/
{{/formParams}} export const {{classname}}Fp = {
let fetchParams = { {{#operation}}
method: '{{httpMethod}}', /** {{#summary}}
headers: headerParams, * {{summary}}{{/summary}}{{#notes}}
{{#bodyParam}}body: JSON.stringify(params.{{paramName}}), * {{notes}}{{/notes}}{{#allParams}}
{{/bodyParam}} * @param {{paramName}} {{description}}{{/allParams}}
{{#hasFormParams}}body: querystring.stringify(formParams), */
{{/hasFormParams}} {{nickname}}({{#hasParams}}params: { {{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}; {{/allParams}} }{{/hasParams}}): (fetch: FetchAPI, basePath?: string) => Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}any{{/returnType}}> {
const fetchArgs = {{classname}}FetchParamCreactor.{{nickname}}({{#hasParams}}params{{/hasParams}});
}; return (fetch: FetchAPI = isomorphicFetch, basePath: string = BASE_PATH) => {
return fetch(basePath + fetchArgs.url, fetchArgs.options).then((response) => {
if (extraFetchParams) {
fetchParams = assign(fetchParams, extraFetchParams);
}
let localVarPathWithQueryParameters = localVarPath + (localVarPath.indexOf('?') !== -1 ? '&' : '?') + querystring.stringify(queryParameters);
return fetch(localVarPathWithQueryParameters, fetchParams).then((response) => {
if (response.status >= 200 && response.status < 300) { if (response.status >= 200 && response.status < 300) {
return response.json(); return response{{#returnType}}.json(){{/returnType}};
} else { } else {
let error = new Error(response.statusText); throw response;
(error as any).response = response;
throw error;
} }
}); });
} };
},
{{/operation}} {{/operation}}
};
/**
* {{classname}} - object-oriented interface{{#description}}
* {{&description}}{{/description}}
*/
export class {{classname}} extends BaseAPI {
{{#operation}}
/** {{#summary}}
* {{summary}}{{/summary}}{{#notes}}
* {{notes}}{{/notes}}{{#allParams}}
* @param {{paramName}} {{description}}{{/allParams}}
*/
{{nickname}}({{#hasParams}}params: { {{#allParams}} {{paramName}}{{^required}}?{{/required}}: {{{dataType}}};{{/allParams}} }{{/hasParams}}) {
return {{classname}}Fp.{{nickname}}({{#hasParams}}params{{/hasParams}})(this.fetch, this.basePath);
} }
//} {{/operation}}
}
{{/operations}} {{/operations}}
{{/apis}} {{/apis}}
{{/apiInfo}} {{/apiInfo}}

View File

@ -1,18 +0,0 @@
export function assign (target: any, ...args: any[]) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var output = Object(target);
for (let source of args) {
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};

View File

@ -1,15 +1,15 @@
{ {
"name": "{{#npmName}}{{{npmName}}}{{/npmName}}{{^npmName}}typescript-fetch-api{{/npmName}}", "name": "{{#npmName}}{{{npmName}}}{{/npmName}}{{^npmName}}typescript-fetch-api{{/npmName}}",
"version": "{{#npmVersion}}{{{npmVersion}}}{{/npmVersion}}{{^npmVersion}}0.0.0{{/npmVersion}}", "version": "{{#npmVersion}}{{{npmVersion}}}{{/npmVersion}}{{^npmVersion}}0.0.0{{/npmVersion}}",
"private": true,
"main": "./dist/api.js", "main": "./dist/api.js",
"browser": "./dist/api.js", "browser": "./dist/api.js",
"typings": "./dist/api.d.ts", "typings": "./dist/api.d.ts",
"dependencies": { "dependencies": {
"isomorphic-fetch": "^2.2.1" {{^supportsES6}}"core-js": "^2.4.0",
{{/supportsES6}}"isomorphic-fetch": "^2.2.1"
}, },
"scripts" : { "scripts" : {
"install" : "typings install && tsc" "prepublish" : "typings install && tsc"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^1.8.10", "typescript": "^1.8.10",

View File

@ -4,7 +4,8 @@
"target": "{{#supportsES6}}es6{{/supportsES6}}{{^supportsES6}}es5{{/supportsES6}}", "target": "{{#supportsES6}}es6{{/supportsES6}}{{^supportsES6}}es5{{/supportsES6}}",
"module": "commonjs", "module": "commonjs",
"noImplicitAny": true, "noImplicitAny": true,
"outDir": "dist" "outDir": "dist",
"rootDir": "."
}, },
"exclude": [ "exclude": [
"dist", "dist",

View File

@ -1,9 +1,9 @@
{ {
"version": false, "version": false,
"dependencies": {}, "dependencies": {},
"ambientDependencies": { "ambientDependencies": { {{^supportsES6}}
{{^supportsES6}} "es6-promise": "registry:dt/es6-promise#0.0.0+20160423074304", "core-js": "registry:dt/core-js#0.0.0+20160317120654",{{/supportsES6}}
{{/supportsES6}} "node": "registry:dt/node#4.0.0+20160423143914", "node": "registry:dt/node#4.0.0+20160423143914",
"isomorphic-fetch": "registry:dt/isomorphic-fetch#0.0.0+20160505171433" "isomorphic-fetch": "registry:dt/isomorphic-fetch#0.0.0+20160505171433"
} }
} }

View File

@ -0,0 +1,51 @@
#!/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 swagger-petstore-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 crediential 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'

View File

@ -0,0 +1,39 @@
# Built application files
*.apk
*.ap_
# Files for the Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# Intellij
*.iml
# Keystore files
*.jks

View File

@ -37,11 +37,24 @@
<version>${android-platform-version}</version> <version>${android-platform-version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<properties> <properties>
<swagger-annotations-version>1.5.0</swagger-annotations-version> <swagger-annotations-version>1.5.8</swagger-annotations-version>
<httpcomponents-httpcore-version>4.4.4</httpcomponents-httpcore-version> <httpcomponents-httpcore-version>4.4.4</httpcomponents-httpcore-version>
<httpcomponents-httpmime-version>4.5.2</httpcomponents-httpmime-version> <httpcomponents-httpmime-version>4.5.2</httpcomponents-httpmime-version>
<google-code-gson-version>2.3.1</google-code-gson-version> <google-code-gson-version>2.6.2</google-code-gson-version>
<volley-library-version>1.0.19</volley-library-version> <volley-library-version>1.0.19</volley-library-version>
<android-platform-version>4.1.1.4</android-platform-version> <android-platform-version>4.1.1.4</android-platform-version>
</properties> </properties>

View File

@ -20,6 +20,11 @@ namespace {{packageName}}.Client
/// </summary> /// </summary>
public class ApiClient public class ApiClient
{ {
private JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ApiClient" /> class /// Initializes a new instance of the <see cref="ApiClient" /> class
/// with default configuration and base path ({{basePath}}). /// with default configuration and base path ({{basePath}}).
@ -305,7 +310,7 @@ namespace {{packageName}}.Client
// at this point, it must be a model (json) // at this point, it must be a model (json)
try try
{ {
return JsonConvert.DeserializeObject(response.Content, type); return JsonConvert.DeserializeObject(response.Content, type, serializerSettings);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RestSharp;
namespace {{packageName}}.Client
{
/// <summary>
/// Represents configuration aspects required to interact with the API endpoints.
/// </summary>
public interface IApiAccessor
{
/// <summary>
/// Gets or sets the configuration object
/// </summary>
/// <value>An instance of the Configuration</value>
Configuration Configuration {get; set;}
/// <summary>
/// Gets the base path of the API client.
/// </summary>
/// <value>The base path</value>
String GetBasePath();
}
}

View File

@ -13,7 +13,7 @@ namespace {{packageName}}.Api
/// <summary> /// <summary>
/// Represents a collection of functions to interact with the API endpoints /// Represents a collection of functions to interact with the API endpoints
/// </summary> /// </summary>
public interface I{{classname}} public interface I{{classname}} : IApiAccessor
{ {
#region Synchronous Operations #region Synchronous Operations
{{#operation}} {{#operation}}
@ -72,7 +72,7 @@ namespace {{packageName}}.Api
/// <summary> /// <summary>
/// Represents a collection of functions to interact with the API endpoints /// Represents a collection of functions to interact with the API endpoints
/// </summary> /// </summary>
public class {{classname}} : I{{classname}} public partial class {{classname}} : I{{classname}}
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="{{classname}}"/> class. /// Initializes a new instance of the <see cref="{{classname}}"/> class.
@ -122,7 +122,7 @@ namespace {{packageName}}.Api
/// Sets the base path of the API client. /// Sets the base path of the API client.
/// </summary> /// </summary>
/// <value>The base path</value> /// <value>The base path</value>
[Obsolete("SetBasePath is deprecated, please do 'Configuraiton.ApiClient = new ApiClient(\"http://new-path\")' instead.")] [Obsolete("SetBasePath is deprecated, please do 'Configuration.ApiClient = new ApiClient(\"http://new-path\")' instead.")]
public void SetBasePath(String basePath) public void SetBasePath(String basePath)
{ {
// do nothing // do nothing

View File

@ -24,6 +24,13 @@
public {{{datatypeWithEnum}}}{{#isEnum}}?{{/isEnum}} {{name}} { get; set; } public {{{datatypeWithEnum}}}{{#isEnum}}?{{/isEnum}} {{name}} { get; set; }
{{/isEnum}} {{/isEnum}}
{{/vars}} {{/vars}}
{{#hasRequired}}
/// <summary>
/// Initializes a new instance of the <see cref="{{classname}}" /> class.
/// </summary>
[JsonConstructorAttribute]
protected {{classname}}() { }
{{/hasRequired}}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="{{classname}}" /> class. /// Initializes a new instance of the <see cref="{{classname}}" /> class.
/// </summary> /// </summary>

View File

@ -2,7 +2,7 @@
NSString *const {{classPrefix}}ResponseObjectErrorKey = @"{{classPrefix}}ResponseObject"; NSString *const {{classPrefix}}ResponseObjectErrorKey = @"{{classPrefix}}ResponseObject";
static long requestId = 0; static NSUInteger requestId = 0;
static bool offlineState = false; static bool offlineState = false;
static NSMutableSet * queuedRequests = nil; static NSMutableSet * queuedRequests = nil;
static bool cacheEnabled = false; static bool cacheEnabled = false;
@ -36,7 +36,7 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
@interface {{classPrefix}}ApiClient () @interface {{classPrefix}}ApiClient ()
@property (readwrite, nonatomic) NSDictionary *HTTPResponseHeaders; @property (nonatomic, strong) NSDictionary* HTTPResponseHeaders;
@end @end
@ -88,49 +88,6 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
[self.requestSerializer setValue:value forHTTPHeaderField:forKey]; [self.requestSerializer setValue:value forHTTPHeaderField:forKey];
} }
#pragma mark - Log Methods
+ (void)debugLog:(NSString *)method
message:(NSString *)format, ... {
{{classPrefix}}Configuration *config = [{{classPrefix}}Configuration sharedConfig];
if (!config.debug) {
return;
}
NSMutableString *message = [NSMutableString stringWithCapacity:1];
if (method) {
[message appendString:[NSString stringWithFormat:@"%@: ", method]];
}
va_list args;
va_start(args, format);
[message appendString:[[NSString alloc] initWithFormat:format arguments:args]];
// If set logging file handler, log into file,
// otherwise log into console.
if (config.loggingFileHanlder) {
[config.loggingFileHanlder seekToEndOfFile];
[config.loggingFileHanlder writeData:[message dataUsingEncoding:NSUTF8StringEncoding]];
}
else {
NSLog(@"%@", message);
}
va_end(args);
}
- (void)logResponse:(NSURLResponse *)response responseObject:(id)responseObject request:(NSURLRequest *)request error:(NSError *)error {
NSString *message = [NSString stringWithFormat:@"\n[DEBUG] HTTP request body \n~BEGIN~\n %@\n~END~\n"\
"[DEBUG] HTTP response body \n~BEGIN~\n %@\n~END~\n",
[[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding],
responseObject];
{{classPrefix}}DebugLog(message);
}
#pragma mark - Cache Methods #pragma mark - Cache Methods
+(void)clearCache { +(void)clearCache {
@ -151,70 +108,6 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
[NSURLCache setSharedURLCache:cache]; [NSURLCache setSharedURLCache:cache];
} }
#pragma mark - Utility Methods
/*
* Detect `Accept` from accepts
*/
+ (NSString *) selectHeaderAccept:(NSArray *)accepts {
if (accepts == nil || [accepts count] == 0) {
return @"";
}
NSMutableArray *lowerAccepts = [[NSMutableArray alloc] initWithCapacity:[accepts count]];
for (NSString *string in accepts) {
NSString * lowerAccept = [string lowercaseString];
// use rangeOfString instead of containsString for iOS 7 support
if ([lowerAccept rangeOfString:@"application/json"].location != NSNotFound) {
return @"application/json";
}
[lowerAccepts addObject:lowerAccept];
}
if (lowerAccepts.count == 1) {
return [lowerAccepts firstObject];
}
return [lowerAccepts componentsJoinedByString:@", "];
}
/*
* Detect `Content-Type` from contentTypes
*/
+ (NSString *) selectHeaderContentType:(NSArray *)contentTypes
{
if (contentTypes == nil || [contentTypes count] == 0) {
return @"application/json";
}
NSMutableArray *lowerContentTypes = [[NSMutableArray alloc] initWithCapacity:[contentTypes count]];
[contentTypes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[lowerContentTypes addObject:[obj lowercaseString]];
}];
if ([lowerContentTypes containsObject:@"application/json"]) {
return @"application/json";
}
else {
return lowerContentTypes[0];
}
}
+ (NSString*)escape:(id)unescaped {
if ([unescaped isKindOfClass:[NSString class]]){
return (NSString *)CFBridgingRelease
(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef) unescaped,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8));
}
else {
return [NSString stringWithFormat:@"%@", unescaped];
}
}
#pragma mark - Request Methods #pragma mark - Request Methods
+(unsigned long)requestQueueSize { +(unsigned long)requestQueueSize {
@ -223,14 +116,12 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
+(NSNumber*) nextRequestId { +(NSNumber*) nextRequestId {
@synchronized(self) { @synchronized(self) {
long nextId = ++requestId; return @(++requestId);
{{classPrefix}}DebugLog(@"got id %ld", nextId);
return [NSNumber numberWithLong:nextId];
} }
} }
+(NSNumber*) queueRequest { +(NSNumber*) queueRequest {
NSNumber* requestId = [{{classPrefix}}ApiClient nextRequestId]; NSNumber* requestId = [[self class] nextRequestId];
{{classPrefix}}DebugLog(@"added %@ to request queue", requestId); {{classPrefix}}DebugLog(@"added %@ to request queue", requestId);
[queuedRequests addObject:requestId]; [queuedRequests addObject:requestId];
return requestId; return requestId;
@ -294,7 +185,7 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
if (![strongSelf executeRequestWithId:requestId]) { if (![strongSelf executeRequestWithId:requestId]) {
return; return;
} }
[strongSelf logResponse:response responseObject:responseObject request:request error:error]; {{classPrefix}}DebugLogResponse(response, responseObject,request,error);
strongSelf.HTTPResponseHeaders = {{classPrefix}}__headerFieldsForResponse(response); strongSelf.HTTPResponseHeaders = {{classPrefix}}__headerFieldsForResponse(response);
if(!error) { if(!error) {
completionBlock(responseObject, nil); completionBlock(responseObject, nil);
@ -321,7 +212,7 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
return; return;
} }
strongSelf.HTTPResponseHeaders = {{classPrefix}}__headerFieldsForResponse(response); strongSelf.HTTPResponseHeaders = {{classPrefix}}__headerFieldsForResponse(response);
[strongSelf logResponse:response responseObject:responseObject request:request error:error]; {{classPrefix}}DebugLogResponse(response, responseObject,request,error);
if(error) { if(error) {
NSMutableDictionary *userInfo = [error.userInfo mutableCopy]; NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
if (responseObject) { if (responseObject) {
@ -370,14 +261,13 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
self.requestSerializer = [AFHTTPRequestSerializer serializer]; self.requestSerializer = [AFHTTPRequestSerializer serializer];
} }
else { else {
NSAssert(false, @"unsupport request type %@", requestContentType); NSAssert(NO, @"Unsupported request type %@", requestContentType);
} }
// setting response serializer // setting response serializer
if ([responseContentType isEqualToString:@"application/json"]) { if ([responseContentType isEqualToString:@"application/json"]) {
self.responseSerializer = [{{classPrefix}}JSONResponseSerializer serializer]; self.responseSerializer = [{{classPrefix}}JSONResponseSerializer serializer];
} } else {
else {
self.responseSerializer = [AFHTTPResponseSerializer serializer]; self.responseSerializer = [AFHTTPResponseSerializer serializer];
} }
@ -393,8 +283,9 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
NSMutableString *resourcePath = [NSMutableString stringWithString:path]; NSMutableString *resourcePath = [NSMutableString stringWithString:path];
[pathParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { [pathParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[resourcePath replaceCharactersInRange:[resourcePath rangeOfString:[NSString stringWithFormat:@"%@%@%@", @"{", key, @"}"]] NSString * safeString = ([obj isKindOfClass:[NSString class]]) ? obj : [NSString stringWithFormat:@"%@", obj];
withString:[{{classPrefix}}ApiClient escape:obj]]; safeString = {{classPrefix}}PercentEscapedStringFromString(safeString);
[resourcePath replaceCharactersInRange:[resourcePath rangeOfString:[NSString stringWithFormat:@"{%@}", key]] withString:safeString];
}]; }];
NSMutableURLRequest * request = nil; NSMutableURLRequest * request = nil;
@ -438,10 +329,7 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
} }
// request cache // request cache
BOOL hasHeaderParams = false; BOOL hasHeaderParams = [headerParams count] > 0;
if (headerParams != nil && [headerParams count] > 0) {
hasHeaderParams = true;
}
if (offlineState) { if (offlineState) {
{{classPrefix}}DebugLog(@"%@ cache forced", resourcePath); {{classPrefix}}DebugLog(@"%@ cache forced", resourcePath);
[request setCachePolicy:NSURLRequestReturnCacheDataDontLoad]; [request setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
@ -462,9 +350,7 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
} }
[self.requestSerializer setValue:responseContentType forHTTPHeaderField:@"Accept"]; [self.requestSerializer setValue:responseContentType forHTTPHeaderField:@"Accept"];
[self postProcessRequest:request];
// Always disable cookies!
[request setHTTPShouldHandleCookies:NO];
NSNumber* requestId = [{{classPrefix}}ApiClient queueRequest]; NSNumber* requestId = [{{classPrefix}}ApiClient queueRequest];
if ([responseType isEqualToString:@"NSURL*"] || [responseType isEqualToString:@"NSURL"]) { if ([responseType isEqualToString:@"NSURL*"] || [responseType isEqualToString:@"NSURL"]) {
@ -485,59 +371,66 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
return requestId; return requestId;
} }
//Added for easier override to modify request
-(void)postProcessRequest:(NSMutableURLRequest *)request {
// Always disable cookies!
[request setHTTPShouldHandleCookies:NO];
}
#pragma mark - #pragma mark -
- (NSString*) pathWithQueryParamsToString:(NSString*) path - (NSString*) pathWithQueryParamsToString:(NSString*) path
queryParams:(NSDictionary*) queryParams { queryParams:(NSDictionary*) queryParams {
if(queryParams.count == 0) {
return path;
}
NSString * separator = nil; NSString * separator = nil;
int counter = 0; NSUInteger counter = 0;
NSMutableString * requestUrl = [NSMutableString stringWithFormat:@"%@", path]; NSMutableString * requestUrl = [NSMutableString stringWithFormat:@"%@", path];
if (queryParams != nil){
for(NSString * key in [queryParams keyEnumerator]){
if (counter == 0) separator = @"?";
else separator = @"&";
id queryParam = [queryParams valueForKey:key];
if ([queryParam isKindOfClass:[NSString class]]){
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiClient escape:key], [{{classPrefix}}ApiClient escape:[queryParams valueForKey:key]]]];
}
else if ([queryParam isKindOfClass:[{{classPrefix}}QueryParamCollection class]]){
{{classPrefix}}QueryParamCollection * coll = ({{classPrefix}}QueryParamCollection*) queryParam;
NSArray* values = [coll values];
NSString* format = [coll format];
if ([format isEqualToString:@"csv"]) { NSDictionary *separatorStyles = @{@"csv" : @",",
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, @"tsv" : @"\t",
[{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@","]]]]; @"pipes": @"|"
};
} for(NSString * key in [queryParams keyEnumerator]){
else if ([format isEqualToString:@"tsv"]) { if (counter == 0) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, separator = @"?";
[{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@"\t"]]]]; } else {
separator = @"&";
}
else if ([format isEqualToString:@"pipes"]) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", [values componentsJoinedByString:@"|"]]]];
}
else if ([format isEqualToString:@"multi"]) {
for(id obj in values) {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", obj]]];
counter += 1;
}
}
}
else {
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator,
[{{classPrefix}}ApiClient escape:key], [NSString stringWithFormat:@"%@", [queryParams valueForKey:key]]]];
}
counter += 1;
} }
id queryParam = [queryParams valueForKey:key];
if(!queryParam) {
continue;
}
NSString *safeKey = {{classPrefix}}PercentEscapedStringFromString(key);
if ([queryParam isKindOfClass:[NSString class]]){
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, safeKey, {{classPrefix}}PercentEscapedStringFromString(queryParam)]];
} else if ([queryParam isKindOfClass:[{{classPrefix}}QueryParamCollection class]]){
{{classPrefix}}QueryParamCollection * coll = ({{classPrefix}}QueryParamCollection*) queryParam;
NSArray* values = [coll values];
NSString* format = [coll format];
if([format isEqualToString:@"multi"]) {
for(id obj in values) {
if (counter > 0) {
separator = @"&";
}
NSString * safeValue = {{classPrefix}}PercentEscapedStringFromString([NSString stringWithFormat:@"%@",obj]);
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, safeKey, safeValue]];
counter += 1;
}
continue;
}
NSString * separatorStyle = separatorStyles[format];
NSString * safeValue = {{classPrefix}}PercentEscapedStringFromString([values componentsJoinedByString:separatorStyle]);
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, safeKey, safeValue]];
} else {
NSString * safeValue = {{classPrefix}}PercentEscapedStringFromString([NSString stringWithFormat:@"%@",queryParam]);
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, safeKey, safeValue]];
}
counter += 1;
} }
return requestUrl; return requestUrl;
} }
@ -558,15 +451,17 @@ static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response)
{{classPrefix}}Configuration *config = [{{classPrefix}}Configuration sharedConfig]; {{classPrefix}}Configuration *config = [{{classPrefix}}Configuration sharedConfig];
for (NSString *auth in authSettings) { for (NSString *auth in authSettings) {
NSDictionary *authSetting = [[config authSettings] objectForKey:auth]; NSDictionary *authSetting = [config authSettings][auth];
if(!authSetting) { // auth setting is set only if the key is non-empty
if (authSetting) { // auth setting is set only if the key is non-empty continue;
if ([authSetting[@"in"] isEqualToString:@"header"] && [authSetting[@"key"] length] != 0) { }
[headersWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; NSString *type = authSetting[@"in"];
} NSString *key = authSetting[@"key"];
else if ([authSetting[@"in"] isEqualToString:@"query"] && [authSetting[@"key"] length] != 0) { NSString *value = authSetting[@"value"];
[querysWithAuth setObject:authSetting[@"value"] forKey:authSetting[@"key"]]; if ([type isEqualToString:@"header"] && [key length] > 0 ) {
} headersWithAuth[key] = value;
} else if ([type isEqualToString:@"query"] && [key length] != 0) {
querysWithAuth[key] = value;
} }
} }

View File

@ -7,6 +7,7 @@
#import "{{classPrefix}}Configuration.h" #import "{{classPrefix}}Configuration.h"
#import "{{classPrefix}}ResponseDeserializer.h" #import "{{classPrefix}}ResponseDeserializer.h"
#import "{{classPrefix}}Sanitizer.h" #import "{{classPrefix}}Sanitizer.h"
#import "{{classPrefix}}Logger.h"
/** /**
* NOTE: This class is auto generated by the swagger code generator program. * NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen * https://github.com/swagger-api/swagger-codegen
@ -26,13 +27,6 @@
*/ */
extern NSString *const {{classPrefix}}ResponseObjectErrorKey; extern NSString *const {{classPrefix}}ResponseObjectErrorKey;
/**
* Log debug message macro
*/
#ifndef {{classPrefix}}DebugLog
#define {{classPrefix}}DebugLog(format, ...) [{{classPrefix}}ApiClient debugLog:[NSString stringWithFormat:@"%s", __PRETTY_FUNCTION__] message: format, ##__VA_ARGS__];
#endif
@interface {{classPrefix}}ApiClient : AFHTTPSessionManager @interface {{classPrefix}}ApiClient : AFHTTPSessionManager
@property(nonatomic, assign) NSURLRequestCachePolicy cachePolicy; @property(nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
@ -113,15 +107,6 @@ extern NSString *const {{classPrefix}}ResponseObjectErrorKey;
*/ */
+(void) cancelRequest:(NSNumber*)requestId; +(void) cancelRequest:(NSNumber*)requestId;
/**
* Gets URL encoded NSString
*
* @param unescaped The string which will be escaped.
*
* @return The escaped string.
*/
+(NSString*) escape:(id)unescaped;
/** /**
* Customizes the behavior when the reachability changed * Customizes the behavior when the reachability changed
* *
@ -134,24 +119,6 @@ extern NSString *const {{classPrefix}}ResponseObjectErrorKey;
*/ */
- (void)configureCacheReachibility; - (void)configureCacheReachibility;
/**
* Detects Accept header from accepts NSArray
*
* @param accepts NSArray of header
*
* @return The Accept header
*/
+(NSString *) selectHeaderAccept:(NSArray *)accepts;
/**
* Detects Content-Type header from contentTypes NSArray
*
* @param contentTypes NSArray of header
*
* @return The Content-Type header
*/
+(NSString *) selectHeaderContentType:(NSArray *)contentTypes;
/** /**
* Sets header for request * Sets header for request
* *
@ -172,19 +139,6 @@ extern NSString *const {{classPrefix}}ResponseObjectErrorKey;
queryParams:(NSDictionary **)querys queryParams:(NSDictionary **)querys
WithAuthSettings:(NSArray *)authSettings; WithAuthSettings:(NSArray *)authSettings;
/**
* Logs request and response
*
* @param response NSURLResponse for the HTTP request.
* @param responseObject response object of the HTTP request.
* @param request The HTTP request.
* @param error The error of the HTTP request.
*/
- (void)logResponse:(NSURLResponse *)response
responseObject:(id)responseObject
request:(NSURLRequest *)request
error:(NSError *)error;
/** /**
* Performs request * Performs request
* *
@ -222,9 +176,5 @@ extern NSString *const {{classPrefix}}ResponseObjectErrorKey;
*/ */
- (AFSecurityPolicy *) customSecurityPolicy; - (AFSecurityPolicy *) customSecurityPolicy;
/**
* Log debug message
*/
+(void)debugLog:(NSString *)method message:(NSString *)format, ...;
@end @end

View File

@ -30,12 +30,10 @@
self.username = @""; self.username = @"";
self.password = @""; self.password = @"";
self.accessToken= @""; self.accessToken= @"";
self.tempFolderPath = nil;
self.debug = NO;
self.verifySSL = YES; self.verifySSL = YES;
self.loggingFile = nil;
self.mutableApiKey = [NSMutableDictionary dictionary]; self.mutableApiKey = [NSMutableDictionary dictionary];
self.mutableApiKeyPrefix = [NSMutableDictionary dictionary]; self.mutableApiKeyPrefix = [NSMutableDictionary dictionary];
self.logger = [{{classPrefix}}Logger sharedLogger];
} }
return self; return self;
} }
@ -43,11 +41,13 @@
#pragma mark - Instance Methods #pragma mark - Instance Methods
- (NSString *) getApiKeyWithPrefix:(NSString *)key { - (NSString *) getApiKeyWithPrefix:(NSString *)key {
if ([self.apiKeyPrefix objectForKey:key] && [self.apiKey objectForKey:key] != (id)[NSNull null] && [[self.apiKey objectForKey:key] length] != 0) { // both api key prefix and api key are set NSString *prefix = self.apiKeyPrefix[key];
return [NSString stringWithFormat:@"%@ %@", [self.apiKeyPrefix objectForKey:key], [self.apiKey objectForKey:key]]; NSString *apiKey = self.apiKey[key];
if (prefix && apiKey != (id)[NSNull null] && apiKey.length > 0) { // both api key prefix and api key are set
return [NSString stringWithFormat:@"%@ %@", prefix, apiKey];
} }
else if ([self.apiKey objectForKey:key] != (id)[NSNull null] && [[self.apiKey objectForKey:key] length] != 0) { // only api key, no api key prefix else if (apiKey != (id)[NSNull null] && apiKey.length > 0) { // only api key, no api key prefix
return [NSString stringWithFormat:@"%@", [self.apiKey objectForKey:key]]; return [NSString stringWithFormat:@"%@", self.apiKey[key]];
} }
else { // return empty string if nothing is set else { // return empty string if nothing is set
return @""; return @"";
@ -70,8 +70,7 @@
- (NSString *) getAccessToken { - (NSString *) getAccessToken {
if (self.accessToken.length == 0) { // token not set, return empty string if (self.accessToken.length == 0) { // token not set, return empty string
return @""; return @"";
} } else {
else {
return [NSString stringWithFormat:@"Bearer %@", self.accessToken]; return [NSString stringWithFormat:@"Bearer %@", self.accessToken];
} }
} }
@ -94,20 +93,6 @@
[self.mutableApiKeyPrefix removeObjectForKey:identifier]; [self.mutableApiKeyPrefix removeObjectForKey:identifier];
} }
- (void) setLoggingFile:(NSString *)loggingFile {
// close old file handler
if ([self.loggingFileHanlder isKindOfClass:[NSFileHandle class]]) {
[self.loggingFileHanlder closeFile];
}
_loggingFile = loggingFile;
_loggingFileHanlder = [NSFileHandle fileHandleForWritingAtPath:_loggingFile];
if (_loggingFileHanlder == nil) {
[[NSFileManager defaultManager] createFileAtPath:_loggingFile contents:nil attributes:nil];
_loggingFileHanlder = [NSFileHandle fileHandleForWritingAtPath:_loggingFile];
}
}
#pragma mark - Getter Methods #pragma mark - Getter Methods
- (NSDictionary *) apiKey { - (NSDictionary *) apiKey {
@ -154,4 +139,12 @@
}; };
} }
-(BOOL)debug {
return self.logger.isEnabled;
}
-(void)setDebug:(BOOL)debug {
self.logger.enabled = debug;
}
@end @end

View File

@ -1,5 +1,6 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "{{classPrefix}}ApiClient.h" #import "{{classPrefix}}ApiClient.h"
#import "{{classPrefix}}Logger.h"
/** The `{{classPrefix}}Configuration` class manages the configurations for the sdk. /** The `{{classPrefix}}Configuration` class manages the configurations for the sdk.
* *
@ -12,6 +13,11 @@
@interface {{classPrefix}}Configuration : NSObject @interface {{classPrefix}}Configuration : NSObject
/**
* Default api logger
*/
@property (nonatomic, strong) {{classPrefix}}Logger * logger;
/** /**
* Default api client * Default api client
*/ */
@ -37,7 +43,7 @@
@property (readonly, nonatomic, strong) NSDictionary *apiKeyPrefix; @property (readonly, nonatomic, strong) NSDictionary *apiKeyPrefix;
/** /**
* Usename for HTTP Basic Authentication * Username for HTTP Basic Authentication
*/ */
@property (nonatomic) NSString *username; @property (nonatomic) NSString *username;
@ -56,25 +62,11 @@
*/ */
@property (nonatomic) NSString *tempFolderPath; @property (nonatomic) NSString *tempFolderPath;
/**
* Logging Settings
*/
/** /**
* Debug switch, default false * Debug switch, default false
*/ */
@property (nonatomic) BOOL debug; @property (nonatomic) BOOL debug;
/**
* Debug file location, default log in console
*/
@property (nonatomic) NSString *loggingFile;
/**
* Log file handler, this property is used by sdk internally.
*/
@property (nonatomic, readonly) NSFileHandle *loggingFileHanlder;
/** /**
* Gets configuration singleton instance * Gets configuration singleton instance
*/ */
@ -143,7 +135,7 @@
- (NSString *) getAccessToken; - (NSString *) getAccessToken;
/** /**
* Gets Authentication Setings * Gets Authentication Settings
*/ */
- (NSDictionary *) authSettings; - (NSDictionary *) authSettings;

View File

@ -0,0 +1,74 @@
#import "{{classPrefix}}Logger.h"
@interface {{classPrefix}}Logger ()
@end
@implementation {{classPrefix}}Logger
+ (instancetype) sharedLogger {
static {{classPrefix}}Logger *shardLogger = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shardLogger = [[self alloc] init];
});
return shardLogger;
}
#pragma mark - Log Methods
- (void)debugLog:(NSString *)method
message:(NSString *)format, ... {
if (!self.isEnabled) {
return;
}
NSMutableString *message = [NSMutableString stringWithCapacity:1];
if (method) {
[message appendFormat:@"%@: ", method];
}
va_list args;
va_start(args, format);
[message appendString:[[NSString alloc] initWithFormat:format arguments:args]];
// If set logging file handler, log into file,
// otherwise log into console.
if (self.loggingFileHandler) {
[self.loggingFileHandler seekToEndOfFile];
[self.loggingFileHandler writeData:[message dataUsingEncoding:NSUTF8StringEncoding]];
} else {
NSLog(@"%@", message);
}
va_end(args);
}
- (void)logResponse:(NSURLResponse *)response responseObject:(id)responseObject request:(NSURLRequest *)request error:(NSError *)error {
NSString *message = [NSString stringWithFormat:@"\n[DEBUG] HTTP request body \n~BEGIN~\n %@\n~END~\n"\
"[DEBUG] HTTP response body \n~BEGIN~\n %@\n~END~\n",
[[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding],
responseObject];
{{classPrefix}}DebugLog(message);
}
- (void) setLoggingFile:(NSString *)loggingFile {
if(_loggingFile == loggingFile) {
return;
}
// close old file handler
if ([self.loggingFileHandler isKindOfClass:[NSFileHandle class]]) {
[self.loggingFileHandler closeFile];
}
_loggingFile = loggingFile;
_loggingFileHandler = [NSFileHandle fileHandleForWritingAtPath:_loggingFile];
if (_loggingFileHandler == nil) {
[[NSFileManager defaultManager] createFileAtPath:_loggingFile contents:nil attributes:nil];
_loggingFileHandler = [NSFileHandle fileHandleForWritingAtPath:_loggingFile];
}
}
@end

View File

@ -0,0 +1,54 @@
#import <Foundation/Foundation.h>
/**
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
#ifndef {{classPrefix}}DebugLogResponse
#define {{classPrefix}}DebugLogResponse(response, responseObject,request, error) [[{{classPrefix}}Logger sharedLogger] logResponse:response responseObject:responseObject request:request error:error];
#endif
/**
* Log debug message macro
*/
#ifndef {{classPrefix}}DebugLog
#define {{classPrefix}}DebugLog(format, ...) [[{{classPrefix}}Logger sharedLogger] debugLog:[NSString stringWithFormat:@"%s", __PRETTY_FUNCTION__] message: format, ##__VA_ARGS__];
#endif
@interface {{classPrefix}}Logger : NSObject
+(instancetype)sharedLogger;
/**
* Enabled switch, default NO - default set by {{classPrefix}}Configuration debug property
*/
@property (nonatomic, assign, getter=isEnabled) BOOL enabled;
/**
* Debug file location, default log in console
*/
@property (nonatomic, strong) NSString *loggingFile;
/**
* Log file handler, this property is used by sdk internally.
*/
@property (nonatomic, strong, readonly) NSFileHandle *loggingFileHandler;
/**
* Log debug message
*/
-(void)debugLog:(NSString *)method message:(NSString *)format, ...;
/**
* Logs request and response
*
* @param response NSURLResponse for the HTTP request.
* @param responseObject response object of the HTTP request.
* @param request The HTTP request.
* @param error The error of the HTTP request.
*/
- (void)logResponse:(NSURLResponse *)response responseObject:(id)responseObject request:(NSURLRequest *)request error:(NSError *)error;
@end

View File

@ -3,11 +3,57 @@
#import "{{classPrefix}}QueryParamCollection.h" #import "{{classPrefix}}QueryParamCollection.h"
#import <ISO8601/ISO8601.h> #import <ISO8601/ISO8601.h>
@interface {{classPrefix}}Sanitizer () NSString * {{classPrefix}}PercentEscapedStringFromString(NSString *string) {
static NSString * const k{{classPrefix}}CharactersGeneralDelimitersToEncode = @":#[]@";
static NSString * const k{{classPrefix}}CharactersSubDelimitersToEncode = @"!$&'()*+,;=";
NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
[allowedCharacterSet removeCharactersInString:[k{{classPrefix}}CharactersGeneralDelimitersToEncode stringByAppendingString:k{{classPrefix}}CharactersSubDelimitersToEncode]];
static NSUInteger const batchSize = 50;
NSUInteger index = 0;
NSMutableString *escaped = @"".mutableCopy;
while (index < string.length) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wgnu"
NSUInteger length = MIN(string.length - index, batchSize);
#pragma GCC diagnostic pop
NSRange range = NSMakeRange(index, length);
// To avoid breaking up character sequences such as 👴🏻👮🏽
range = [string rangeOfComposedCharacterSequencesForRange:range];
NSString *substring = [string substringWithRange:range];
NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
[escaped appendString:encoded];
index += range.length;
}
return escaped;
}
@interface SWGSanitizer ()
@property (nonatomic, strong) NSRegularExpression* jsonHeaderTypeExpression;
@end @end
@implementation {{classPrefix}}Sanitizer @implementation SWGSanitizer
static NSString * kApplicationJSONType = @"application/json";
-(instancetype)init {
self = [super init];
if ( !self ) {
return nil;
}
_jsonHeaderTypeExpression = [NSRegularExpression regularExpressionWithPattern:@"(.*)application(.*)json(.*)" options:NSRegularExpressionCaseInsensitive error:nil];
return self;
}
- (id) sanitizeForSerialization:(id) object { - (id) sanitizeForSerialization:(id) object {
if (object == nil) { if (object == nil) {
@ -17,7 +63,7 @@
return object; return object;
} }
else if ([object isKindOfClass:[NSDate class]]) { else if ([object isKindOfClass:[NSDate class]]) {
return [object ISO8601String]; return [self dateParameterToString:object];
} }
else if ([object isKindOfClass:[NSArray class]]) { else if ([object isKindOfClass:[NSArray class]]) {
NSArray *objectArray = object; NSArray *objectArray = object;
@ -61,7 +107,7 @@
return [param stringValue]; return [param stringValue];
} }
else if ([param isKindOfClass:[NSDate class]]) { else if ([param isKindOfClass:[NSDate class]]) {
return [param ISO8601String]; return [self dateParameterToString:param];
} }
else if ([param isKindOfClass:[NSArray class]]) { else if ([param isKindOfClass:[NSArray class]]) {
NSMutableArray *mutableParam = [NSMutableArray array]; NSMutableArray *mutableParam = [NSMutableArray array];
@ -79,4 +125,44 @@
} }
} }
- (NSString *)dateParameterToString:(id)param {
return [param ISO8601String];
}
#pragma mark - Utility Methods
/*
* Detect `Accept` from accepts
*/
- (NSString *) selectHeaderAccept:(NSArray *)accepts {
if (accepts.count == 0) {
return @"";
}
NSMutableArray *lowerAccepts = [[NSMutableArray alloc] initWithCapacity:[accepts count]];
for (NSString *string in accepts) {
if ([self.jsonHeaderTypeExpression matchesInString:string options:0 range:NSMakeRange(0, [string length])].count > 0) {
return kApplicationJSONType;
}
[lowerAccepts addObject:[string lowercaseString]];
}
return [lowerAccepts componentsJoinedByString:@", "];
}
/*
* Detect `Content-Type` from contentTypes
*/
- (NSString *) selectHeaderContentType:(NSArray *)contentTypes {
if (contentTypes.count == 0) {
return kApplicationJSONType;
}
NSMutableArray *lowerContentTypes = [[NSMutableArray alloc] initWithCapacity:[contentTypes count]];
for (NSString *string in contentTypes) {
if([self.jsonHeaderTypeExpression matchesInString:string options:0 range:NSMakeRange(0, [string length])].count > 0){
return kApplicationJSONType;
}
[lowerContentTypes addObject:[string lowercaseString]];
}
return [lowerContentTypes firstObject];
}
@end @end

View File

@ -6,6 +6,8 @@
* Do not edit the class manually. * Do not edit the class manually.
*/ */
extern NSString * {{classPrefix}}PercentEscapedStringFromString(NSString *string);
@protocol {{classPrefix}}Sanitizer <NSObject> @protocol {{classPrefix}}Sanitizer <NSObject>
/** /**
@ -20,6 +22,24 @@
*/ */
- (NSString *) parameterToString: (id) param; - (NSString *) parameterToString: (id) param;
/**
* Detects Accept header from accepts NSArray
*
* @param accepts NSArray of header
*
* @return The Accept header
*/
-(NSString *) selectHeaderAccept:(NSArray *)accepts;
/**
* Detects Content-Type header from contentTypes NSArray
*
* @param contentTypes NSArray of header
*
* @return The Content-Type header
*/
-(NSString *) selectHeaderContentType:(NSArray *)contentTypes;
@end @end
@interface {{classPrefix}}Sanitizer : NSObject <{{classPrefix}}Sanitizer> @interface {{classPrefix}}Sanitizer : NSObject <{{classPrefix}}Sanitizer>

View File

@ -15,7 +15,7 @@ static {{classname}}* singletonAPI = nil;
#pragma mark - Initialize methods #pragma mark - Initialize methods
- (id) init { - (instancetype) init {
self = [super init]; self = [super init];
if (self) { if (self) {
{{classPrefix}}Configuration *config = [{{classPrefix}}Configuration sharedConfig]; {{classPrefix}}Configuration *config = [{{classPrefix}}Configuration sharedConfig];
@ -28,7 +28,7 @@ static {{classname}}* singletonAPI = nil;
return self; return self;
} }
- (id) initWithApiClient:({{classPrefix}}ApiClient *)apiClient { - (instancetype) initWithApiClient:({{classPrefix}}ApiClient *)apiClient {
self = [super init]; self = [super init];
if (self) { if (self) {
self.apiClient = apiClient; self.apiClient = apiClient;
@ -92,9 +92,7 @@ static {{classname}}* singletonAPI = nil;
NSMutableString* resourcePath = [NSMutableString stringWithFormat:@"{{path}}"]; NSMutableString* resourcePath = [NSMutableString stringWithFormat:@"{{path}}"];
// remove format in URL if needed // remove format in URL if needed
if ([resourcePath rangeOfString:@".{format}"].location != NSNotFound) { [resourcePath replaceOccurrencesOfString:@".{format}" withString:@".json" options:0 range:NSMakeRange(0,resourcePath.length)];
[resourcePath replaceCharactersInRange: [resourcePath rangeOfString:@".{format}"] withString:@".json"];
}
NSMutableDictionary *pathParams = [[NSMutableDictionary alloc] init]; NSMutableDictionary *pathParams = [[NSMutableDictionary alloc] init];
{{#pathParams}} {{#pathParams}}
@ -121,22 +119,16 @@ static {{classname}}* singletonAPI = nil;
{{/headerParams}} {{/headerParams}}
// HTTP header `Accept` // HTTP header `Accept`
headerParams[@"Accept"] = [{{classPrefix}}ApiClient selectHeaderAccept:@[{{#produces}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}}]]; NSString *acceptHeader = [self.apiClient.sanitizer selectHeaderAccept:@[{{#produces}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}}]];
if ([headerParams[@"Accept"] length] == 0) { if(acceptHeader.length > 0) {
[headerParams removeObjectForKey:@"Accept"]; headerParams[@"Accept"] = acceptHeader;
} }
// response content type // response content type
NSString *responseContentType; NSString *responseContentType = [[acceptHeader componentsSeparatedByString:@", "] firstObject] ?: @"";
if ([headerParams objectForKey:@"Accept"]) {
responseContentType = [headerParams[@"Accept"] componentsSeparatedByString:@", "][0];
}
else {
responseContentType = @"";
}
// request content type // request content type
NSString *requestContentType = [{{classPrefix}}ApiClient selectHeaderContentType:@[{{#consumes}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}]]; NSString *requestContentType = [self.apiClient.sanitizer selectHeaderContentType:@[{{#consumes}}@"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}]];
// Authentication setting // Authentication setting
NSArray *authSettings = @[{{#authMethods}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}]; NSArray *authSettings = @[{{#authMethods}}@"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}}];

View File

@ -22,13 +22,12 @@
+({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key;
+({{classname}}*) sharedAPI; +({{classname}}*) sharedAPI;
{{#operation}} {{#operation}}
///
///
/// {{{summary}}} /// {{{summary}}}
/// {{#notes}}{{{notes}}}{{/notes}} /// {{#notes}}{{{notes}}}{{/notes}}
/// ///
/// {{#allParams}}@param {{paramName}} {{description}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} /// {{#allParams}}@param {{paramName}} {{description}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}
/// {{/allParams}} /// {{/allParams}}{{#responses}}
/// code:{{{code}}} message:"{{{message}}}"{{#hasMore}},{{/hasMore}}{{/responses}}
/// ///
/// @return {{{returnType}}} /// @return {{{returnType}}}
-(NSNumber*) {{#vendorExtensions.x-objc-operationId}}{{vendorExtensions.x-objc-operationId}}{{/vendorExtensions.x-objc-operationId}}{{^vendorExtensions.x-objc-operationId}}{{nickname}}{{#hasParams}}With{{vendorExtensions.firstParamAltName}}{{/hasParams}}{{^hasParams}}WithCompletionHandler: {{/hasParams}}{{/vendorExtensions.x-objc-operationId}}{{#allParams}}{{#secondaryParam}} -(NSNumber*) {{#vendorExtensions.x-objc-operationId}}{{vendorExtensions.x-objc-operationId}}{{/vendorExtensions.x-objc-operationId}}{{^vendorExtensions.x-objc-operationId}}{{nickname}}{{#hasParams}}With{{vendorExtensions.firstParamAltName}}{{/hasParams}}{{^hasParams}}WithCompletionHandler: {{/hasParams}}{{/vendorExtensions.x-objc-operationId}}{{#allParams}}{{#secondaryParam}}

View File

View File

@ -13,7 +13,7 @@ Pod::Spec.new do |s|
{{#apiInfo}}{{#apis}}{{^hasMore}} {{#apiInfo}}{{#apis}}{{^hasMore}}
s.summary = "{{appName}}" s.summary = "{{appName}}"
s.description = <<-DESC s.description = <<-DESC
{{appDescription}} {{{appDescription}}}
DESC DESC
{{/hasMore}}{{/apis}}{{/apiInfo}} {{/hasMore}}{{/apis}}{{/apiInfo}}
s.platform = :ios, '7.0' s.platform = :ios, '7.0'
@ -29,8 +29,8 @@ Pod::Spec.new do |s|
s.source_files = '{{podName}}/**/*' s.source_files = '{{podName}}/**/*'
s.public_header_files = '{{podName}}/**/*.h' s.public_header_files = '{{podName}}/**/*.h'
s.dependency 'AFNetworking', '~> 2.3' s.dependency 'AFNetworking', '~> 3'
s.dependency 'JSONModel', '~> 1.1' s.dependency 'JSONModel', '~> 1.2'
s.dependency 'ISO8601', '~> 0.3' s.dependency 'ISO8601', '~> 0.5'
end end

View File

@ -55,18 +55,21 @@ class ApiClient
/** /**
* Configuration * Configuration
*
* @var Configuration * @var Configuration
*/ */
protected $config; protected $config;
/** /**
* Object Serializer * Object Serializer
*
* @var ObjectSerializer * @var ObjectSerializer
*/ */
protected $serializer; protected $serializer;
/** /**
* Constructor of the class * Constructor of the class
*
* @param Configuration $config config for this ApiClient * @param Configuration $config config for this ApiClient
*/ */
public function __construct(\{{invokerPackage}}\Configuration $config = null) public function __construct(\{{invokerPackage}}\Configuration $config = null)
@ -81,6 +84,7 @@ class ApiClient
/** /**
* Get the config * Get the config
*
* @return Configuration * @return Configuration
*/ */
public function getConfig() public function getConfig()
@ -90,6 +94,7 @@ class ApiClient
/** /**
* Get the serializer * Get the serializer
*
* @return ObjectSerializer * @return ObjectSerializer
*/ */
public function getSerializer() public function getSerializer()
@ -99,7 +104,9 @@ class ApiClient
/** /**
* Get API key (with prefix if set) * Get API key (with prefix if set)
*
* @param string $apiKeyIdentifier name of apikey * @param string $apiKeyIdentifier name of apikey
*
* @return string API key with the prefix * @return string API key with the prefix
*/ */
public function getApiKeyWithPrefix($apiKeyIdentifier) public function getApiKeyWithPrefix($apiKeyIdentifier)
@ -122,12 +129,14 @@ class ApiClient
/** /**
* Make the HTTP call (Sync) * Make the HTTP call (Sync)
*
* @param string $resourcePath path to method endpoint * @param string $resourcePath path to method endpoint
* @param string $method method to call * @param string $method method to call
* @param array $queryParams parameters to be place in query URL * @param array $queryParams parameters to be place in query URL
* @param array $postData parameters to be placed in POST body * @param array $postData parameters to be placed in POST body
* @param array $headerParams parameters to be place in request header * @param array $headerParams parameters to be place in request header
* @param string $responseType expected response type of the endpoint * @param string $responseType expected response type of the endpoint
*
* @throws \{{invokerPackage}}\ApiException on a non 2xx response * @throws \{{invokerPackage}}\ApiException on a non 2xx response
* @return mixed * @return mixed
*/ */
@ -171,7 +180,7 @@ class ApiClient
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
} }
if (! empty($queryParams)) { if (!empty($queryParams)) {
$url = ($url . '?' . http_build_query($queryParams)); $url = ($url . '?' . http_build_query($queryParams));
} }
@ -216,7 +225,7 @@ class ApiClient
// Make the request // Make the request
$response = curl_exec($curl); $response = curl_exec($curl);
$http_header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); $http_header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$http_header = $this->http_parse_headers(substr($response, 0, $http_header_size)); $http_header = $this->httpParseHeaders(substr($response, 0, $http_header_size));
$http_body = substr($response, $http_header_size); $http_body = substr($response, $http_header_size);
$response_info = curl_getinfo($curl); $response_info = curl_getinfo($curl);
@ -228,7 +237,7 @@ class ApiClient
// Handle the response // Handle the response
if ($response_info['http_code'] == 0) { if ($response_info['http_code'] == 0) {
throw new ApiException("API call to $url timed out: ".serialize($response_info), 0, null, null); throw new ApiException("API call to $url timed out: ".serialize($response_info), 0, null, null);
} elseif ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299 ) { } elseif ($response_info['http_code'] >= 200 && $response_info['http_code'] <= 299) {
// return raw body if response is a file // return raw body if response is a file
if ($responseType == '\SplFileObject' || $responseType == 'string') { if ($responseType == '\SplFileObject' || $responseType == 'string') {
return array($http_body, $response_info['http_code'], $http_header); return array($http_body, $response_info['http_code'], $http_header);
@ -246,7 +255,9 @@ class ApiClient
throw new ApiException( throw new ApiException(
"[".$response_info['http_code']."] Error connecting to the API ($url)", "[".$response_info['http_code']."] Error connecting to the API ($url)",
$response_info['http_code'], $http_header, $data $response_info['http_code'],
$http_header,
$data
); );
} }
return array($data, $response_info['http_code'], $http_header); return array($data, $response_info['http_code'], $http_header);
@ -295,37 +306,32 @@ class ApiClient
* *
* @return string[] Array of HTTP response heaers * @return string[] Array of HTTP response heaers
*/ */
protected function http_parse_headers($raw_headers) protected function httpParseHeaders($raw_headers)
{ {
// ref/credit: http://php.net/manual/en/function.http-parse-headers.php#112986 // ref/credit: http://php.net/manual/en/function.http-parse-headers.php#112986
$headers = array(); $headers = array();
$key = ''; $key = '';
foreach(explode("\n", $raw_headers) as $h) foreach (explode("\n", $raw_headers) as $h) {
{
$h = explode(':', $h, 2); $h = explode(':', $h, 2);
if (isset($h[1])) if (isset($h[1])) {
{ if (!isset($headers[$h[0]])) {
if (!isset($headers[$h[0]]))
$headers[$h[0]] = trim($h[1]); $headers[$h[0]] = trim($h[1]);
elseif (is_array($headers[$h[0]])) } elseif (is_array($headers[$h[0]])) {
{
$headers[$h[0]] = array_merge($headers[$h[0]], array(trim($h[1]))); $headers[$h[0]] = array_merge($headers[$h[0]], array(trim($h[1])));
} } else {
else
{
$headers[$h[0]] = array_merge(array($headers[$h[0]]), array(trim($h[1]))); $headers[$h[0]] = array_merge(array($headers[$h[0]]), array(trim($h[1])));
} }
$key = $h[0]; $key = $h[0];
} } else {
else if (substr($h[0], 0, 1) == "\t") {
{
if (substr($h[0], 0, 1) == "\t")
$headers[$key] .= "\r\n\t".trim($h[0]); $headers[$key] .= "\r\n\t".trim($h[0]);
elseif (!$key) } elseif (!$key) {
$headers[0] = trim($h[0]);trim($h[0]); $headers[0] = trim($h[0]);
}
trim($h[0]);
} }
} }

View File

@ -48,30 +48,34 @@ class ApiException extends Exception
/** /**
* The HTTP body of the server response either as Json or string. * The HTTP body of the server response either as Json or string.
*
* @var mixed * @var mixed
*/ */
protected $responseBody; protected $responseBody;
/** /**
* The HTTP header of the server response. * The HTTP header of the server response.
*
* @var string[] * @var string[]
*/ */
protected $responseHeaders; protected $responseHeaders;
/** /**
* The deserialized response object * The deserialized response object
*
* @var $responseObject; * @var $responseObject;
*/ */
protected $responseObject; protected $responseObject;
/** /**
* Constructor * Constructor
*
* @param string $message Error message * @param string $message Error message
* @param int $code HTTP status code * @param int $code HTTP status code
* @param string $responseHeaders HTTP response header * @param string $responseHeaders HTTP response header
* @param mixed $responseBody HTTP body of the server response either as Json or string * @param mixed $responseBody HTTP body of the server response either as Json or string
*/ */
public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) public function __construct($message = "", $code = 0, $responseHeaders = null, $responseBody = null)
{ {
parent::__construct($message, $code); parent::__construct($message, $code);
$this->responseHeaders = $responseHeaders; $this->responseHeaders = $responseHeaders;
@ -100,7 +104,9 @@ class ApiException extends Exception
/** /**
* Sets the deseralized response object (during deserialization) * Sets the deseralized response object (during deserialization)
*
* @param mixed $obj Deserialized response object * @param mixed $obj Deserialized response object
*
* @return void * @return void
*/ */
public function setResponseObject($obj) public function setResponseObject($obj)

View File

@ -185,7 +185,7 @@ class ObjectSerializer
* *
* @return string * @return string
*/ */
public function serializeCollection(array $collection, $collectionFormat, $allowCollectionFormatMulti=false) public function serializeCollection(array $collection, $collectionFormat, $allowCollectionFormatMulti = false)
{ {
if ($allowCollectionFormatMulti && ('multi' === $collectionFormat)) { if ($allowCollectionFormatMulti && ('multi' === $collectionFormat)) {
// http_build_query() almost does the job for us. We just // http_build_query() almost does the job for us. We just
@ -219,7 +219,7 @@ class ObjectSerializer
* *
* @return object an instance of $class * @return object an instance of $class
*/ */
public static function deserialize($data, $class, $httpHeaders=null, $discriminator=null) public static function deserialize($data, $class, $httpHeaders = null, $discriminator = null)
{ {
if (null === $data) { if (null === $data) {
return null; return null;
@ -261,16 +261,20 @@ class ObjectSerializer
return $data; return $data;
} elseif ($class === '\SplFileObject') { } elseif ($class === '\SplFileObject') {
// determine file name // determine file name
if (array_key_exists('Content-Disposition', $httpHeaders) && preg_match('/inline; filename=[\'"]?([^\'"\s]+)[\'"]?$/i', $httpHeaders['Content-Disposition'], $match)) { if (array_key_exists('Content-Disposition', $httpHeaders) &&
preg_match('/inline; filename=[\'"]?([^\'"\s]+)[\'"]?$/i', $httpHeaders['Content-Disposition'], $match)) {
$filename = Configuration::getDefaultConfiguration()->getTempFolderPath() . sanitizeFilename($match[1]); $filename = Configuration::getDefaultConfiguration()->getTempFolderPath() . sanitizeFilename($match[1]);
} else { } else {
$filename = tempnam(Configuration::getDefaultConfiguration()->getTempFolderPath(), ''); $filename = tempnam(Configuration::getDefaultConfiguration()->getTempFolderPath(), '');
} }
$deserialized = new \SplFileObject($filename, "w"); $deserialized = new \SplFileObject($filename, "w");
$byte_written = $deserialized->fwrite($data); $byte_written = $deserialized->fwrite($data);
error_log("[INFO] Written $byte_written byte to $filename. Please move the file to a proper folder or delete the temp file after processing.\n", 3, Configuration::getDefaultConfiguration()->getDebugFile());
return $deserialized;
if (Configuration::getDefaultConfiguration()->getDebug()) {
error_log("[DEBUG] Written $byte_written byte to $filename. Please move the file to a proper folder or delete the temp file after processing.\n", 3, Configuration::getDefaultConfiguration()->getDebugFile());
}
return $deserialized;
} else { } else {
// If a discriminator is defined and points to a valid subclass, use it. // If a discriminator is defined and points to a valid subclass, use it.
if (!empty($discriminator) && isset($data->{$discriminator}) && is_string($data->{$discriminator})) { if (!empty($discriminator) && isset($data->{$discriminator}) && is_string($data->{$discriminator})) {

View File

@ -52,15 +52,17 @@ use \{{invokerPackage}}\ObjectSerializer;
/** /**
* API Client * API Client
*
* @var \{{invokerPackage}}\ApiClient instance of the ApiClient * @var \{{invokerPackage}}\ApiClient instance of the ApiClient
*/ */
protected $apiClient; protected $apiClient;
/** /**
* Constructor * Constructor
*
* @param \{{invokerPackage}}\ApiClient|null $apiClient The api client to use * @param \{{invokerPackage}}\ApiClient|null $apiClient The api client to use
*/ */
function __construct(\{{invokerPackage}}\ApiClient $apiClient = null) public function __construct(\{{invokerPackage}}\ApiClient $apiClient = null)
{ {
if ($apiClient == null) { if ($apiClient == null) {
$apiClient = new ApiClient(); $apiClient = new ApiClient();
@ -72,6 +74,7 @@ use \{{invokerPackage}}\ObjectSerializer;
/** /**
* Get API client * Get API client
*
* @return \{{invokerPackage}}\ApiClient get the API client * @return \{{invokerPackage}}\ApiClient get the API client
*/ */
public function getApiClient() public function getApiClient()
@ -81,7 +84,9 @@ use \{{invokerPackage}}\ObjectSerializer;
/** /**
* Set the API client * Set the API client
*
* @param \{{invokerPackage}}\ApiClient $apiClient set the API client * @param \{{invokerPackage}}\ApiClient $apiClient set the API client
*
* @return {{classname}} * @return {{classname}}
*/ */
public function setApiClient(\{{invokerPackage}}\ApiClient $apiClient) public function setApiClient(\{{invokerPackage}}\ApiClient $apiClient)
@ -92,28 +97,30 @@ use \{{invokerPackage}}\ObjectSerializer;
{{#operation}} {{#operation}}
/** /**
* {{{operationId}}} * Operation {{{operationId}}}
* *
* {{{summary}}} * {{{summary}}}.
* *
{{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} {{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{/allParams}} *
* @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
* @throws \{{invokerPackage}}\ApiException on non-2xx response * @throws \{{invokerPackage}}\ApiException on non-2xx response
*/ */
public function {{operationId}}({{#allParams}}${{paramName}}{{^required}} = null{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) public function {{operationId}}({{#allParams}}${{paramName}}{{^required}} = null{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
{ {
list($response) = $this->{{operationId}}WithHttpInfo ({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); list($response) = $this->{{operationId}}WithHttpInfo({{#allParams}}${{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
return $response; return $response;
} }
/** /**
* {{{operationId}}}WithHttpInfo * Operation {{{operationId}}}WithHttpInfo
* *
* {{{summary}}} * {{{summary}}}.
* *
{{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} {{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{#required}}(required){{/required}}{{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
{{/allParams}} * @return Array of {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}null{{/returnType}}, HTTP status code, HTTP response headers (array of strings) {{/allParams}} *
* @return Array of {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}null{{/returnType}}, HTTP status code, HTTP response headers (array of strings)
* @throws \{{invokerPackage}}\ApiException on non-2xx response * @throws \{{invokerPackage}}\ApiException on non-2xx response
*/ */
public function {{operationId}}WithHttpInfo({{#allParams}}${{paramName}}{{^required}} = null{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) public function {{operationId}}WithHttpInfo({{#allParams}}${{paramName}}{{^required}} = null{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
@ -208,7 +215,7 @@ use \{{invokerPackage}}\ObjectSerializer;
if (function_exists('curl_file_create')) { if (function_exists('curl_file_create')) {
$formParams['{{baseName}}'] = curl_file_create($this->apiClient->getSerializer()->toFormValue(${{paramName}})); $formParams['{{baseName}}'] = curl_file_create($this->apiClient->getSerializer()->toFormValue(${{paramName}}));
} else { } else {
$formParams['{{baseName}}'] = '@' . $this->apiClient->getSerializer()->toFormValue(${{paramName}}); $formParams['{{baseName}}'] = '@' . $this->apiClient->getSerializer()->toFormValue(${{paramName}});
} }
{{/isFile}} {{/isFile}}
{{^isFile}} {{^isFile}}
@ -244,9 +251,12 @@ use \{{invokerPackage}}\ObjectSerializer;
// make the API Call // make the API Call
try { try {
list($response, $statusCode, $httpHeader) = $this->apiClient->callApi( list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
$resourcePath, '{{httpMethod}}', $resourcePath,
$queryParams, $httpBody, '{{httpMethod}}',
$headerParams{{#returnType}}, '{{returnType}}'{{/returnType}} $queryParams,
$httpBody,
$headerParams{{#returnType}},
'{{returnType}}'{{/returnType}}
); );
{{#returnType}} {{#returnType}}
if (!$response) { if (!$response) {
@ -254,15 +264,20 @@ use \{{invokerPackage}}\ObjectSerializer;
} }
return array($this->apiClient->getSerializer()->deserialize($response, '{{returnType}}', $httpHeader{{#discriminator}}, '{{discriminator}}'{{/discriminator}}), $statusCode, $httpHeader); return array($this->apiClient->getSerializer()->deserialize($response, '{{returnType}}', $httpHeader{{#discriminator}}, '{{discriminator}}'{{/discriminator}}), $statusCode, $httpHeader);
{{/returnType}}{{^returnType}} {{/returnType}}
{{^returnType}}
return array(null, $statusCode, $httpHeader); return array(null, $statusCode, $httpHeader);
{{/returnType}} {{/returnType}}
} catch (ApiException $e) { } catch (ApiException $e) {
switch ($e->getCode()) { {{#responses}}{{#dataType}} switch ($e->getCode()) {
{{^isWildcard}}case {{code}}:{{/isWildcard}}{{#isWildcard}}default:{{/isWildcard}} {{#responses}}
$data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '{{dataType}}', $e->getResponseHeaders()); {{#dataType}}
$e->setResponseObject($data); {{^isWildcard}}case {{code}}:{{/isWildcard}}{{#isWildcard}}default:{{/isWildcard}}
break;{{/dataType}}{{/responses}} $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '{{dataType}}', $e->getResponseHeaders());
$e->setResponseObject($data);
break;
{{/dataType}}
{{/responses}}
} }
throw $e; throw $e;

View File

@ -53,14 +53,16 @@ use \{{invokerPackage}}\ObjectSerializer;
/** /**
* Setup before running each test case * Setup before running each test case
*/ */
public static function setUpBeforeClass() { public static function setUpBeforeClass()
{
} }
/** /**
* Clean up after running each test case * Clean up after running each test case
*/ */
public static function tearDownAfterClass() { public static function tearDownAfterClass()
{
} }
@ -68,10 +70,11 @@ use \{{invokerPackage}}\ObjectSerializer;
/** /**
* Test case for {{{operationId}}} * Test case for {{{operationId}}}
* *
* {{{summary}}} * {{{summary}}}.
* *
*/ */
public function test_{{operationId}}() { public function test{{vendorExtensions.x-testOperationId}}()
{
} }
{{/operation}} {{/operation}}

View File

@ -9,6 +9,7 @@
* new \{{invokerPackage}}\Baz\Qux; * new \{{invokerPackage}}\Baz\Qux;
* *
* @param string $class The fully-qualified class name. * @param string $class The fully-qualified class name.
*
* @return void * @return void
*/ */
spl_autoload_register(function ($class) { spl_autoload_register(function ($class) {

View File

@ -47,7 +47,7 @@ namespace {{invokerPackage}};
class Configuration class Configuration
{ {
private static $_defaultConfiguration = null; private static $defaultConfiguration = null;
/** /**
* Associate array to store API key(s) * Associate array to store API key(s)
@ -487,11 +487,11 @@ class Configuration
*/ */
public static function getDefaultConfiguration() public static function getDefaultConfiguration()
{ {
if (self::$_defaultConfiguration == null) { if (self::$defaultConfiguration == null) {
self::$_defaultConfiguration = new Configuration(); self::$defaultConfiguration = new Configuration();
} }
return self::$_defaultConfiguration; return self::$defaultConfiguration;
} }
/** /**
@ -503,7 +503,7 @@ class Configuration
*/ */
public static function setDefaultConfiguration(Configuration $config) public static function setDefaultConfiguration(Configuration $config)
{ {
self::$_defaultConfiguration = $config; self::$defaultConfiguration = $config;
} }
/** /**
@ -522,5 +522,4 @@ class Configuration
return $report; return $report;
} }
} }

View File

@ -41,7 +41,9 @@ use \ArrayAccess;
* {{classname}} Class Doc Comment * {{classname}} Class Doc Comment
* *
* @category Class * @category Class
{{#description}}
* @description {{description}} * @description {{description}}
{{/description}}
* @package {{invokerPackage}} * @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen * @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
@ -53,18 +55,19 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
* The original name of the model. * The original name of the model.
* @var string * @var string
*/ */
static $swaggerModelName = '{{name}}'; protected static $swaggerModelName = '{{name}}';
/** /**
* Array of property to type mappings. Used for (de)serialization * Array of property to type mappings. Used for (de)serialization
* @var string[] * @var string[]
*/ */
static $swaggerTypes = array( protected static $swaggerTypes = array(
{{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}}, {{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}},
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
static function swaggerTypes() { public static function swaggerTypes()
{
return self::$swaggerTypes{{#parentSchema}} + parent::swaggerTypes(){{/parentSchema}}; return self::$swaggerTypes{{#parentSchema}} + parent::swaggerTypes(){{/parentSchema}};
} }
@ -72,12 +75,13 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
* Array of attributes where the key is the local name, and the value is the original name * Array of attributes where the key is the local name, and the value is the original name
* @var string[] * @var string[]
*/ */
static $attributeMap = array( protected static $attributeMap = array(
{{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}}, {{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}},
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
static function attributeMap() { public static function attributeMap()
{
return {{#parentSchema}}parent::attributeMap() + {{/parentSchema}}self::$attributeMap; return {{#parentSchema}}parent::attributeMap() + {{/parentSchema}}self::$attributeMap;
} }
@ -85,12 +89,13 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
* Array of attributes to setter functions (for deserialization of responses) * Array of attributes to setter functions (for deserialization of responses)
* @var string[] * @var string[]
*/ */
static $setters = array( protected static $setters = array(
{{#vars}}'{{name}}' => '{{setter}}'{{#hasMore}}, {{#vars}}'{{name}}' => '{{setter}}'{{#hasMore}},
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
static function setters() { public static function setters()
{
return {{#parentSchema}}parent::setters() + {{/parentSchema}}self::$setters; return {{#parentSchema}}parent::setters() + {{/parentSchema}}self::$setters;
} }
@ -98,12 +103,13 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
* Array of attributes to getter functions (for serialization of requests) * Array of attributes to getter functions (for serialization of requests)
* @var string[] * @var string[]
*/ */
static $getters = array( protected static $getters = array(
{{#vars}}'{{name}}' => '{{getter}}'{{#hasMore}}, {{#vars}}'{{name}}' => '{{getter}}'{{#hasMore}},
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
static function getters() { public static function getters()
{
return {{#parentSchema}}parent::getters() + {{/parentSchema}}self::$getters; return {{#parentSchema}}parent::getters() + {{/parentSchema}}self::$getters;
} }
@ -115,7 +121,8 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
* Gets allowable values of the enum * Gets allowable values of the enum
* @return string[] * @return string[]
*/ */
public function {{getter}}AllowableValues() { public function {{getter}}AllowableValues()
{
return [ return [
{{#allowableValues}}{{#enumVars}}self::{{datatypeWithEnum}}_{{{name}}},{{^-last}} {{#allowableValues}}{{#enumVars}}self::{{datatypeWithEnum}}_{{{name}}},{{^-last}}
{{/-last}}{{/enumVars}}{{/allowableValues}} {{/-last}}{{/enumVars}}{{/allowableValues}}
@ -155,45 +162,45 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
* *
* @return array invalid properties with reasons * @return array invalid properties with reasons
*/ */
public function list_invalid_properties() public function listInvalidProperties()
{ {
$invalid_properties = array(); $invalid_properties = array();
{{#vars}} {{#vars}}
{{#required}} {{#required}}
if ($this->container['{{name}}'] === null) { if ($this->container['{{name}}'] === null) {
$invalid_properties[] = "'${{name}}' can't be null"; $invalid_properties[] = "'{{name}}' can't be null";
} }
{{/required}} {{/required}}
{{#isEnum}} {{#isEnum}}
$allowed_values = array({{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}); $allowed_values = array({{#allowableValues}}{{#values}}"{{{this}}}"{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}});
if (!in_array($this->container['{{name}}'], $allowed_values)) { if (!in_array($this->container['{{name}}'], $allowed_values)) {
$invalid_properties[] = "invalid value for '${{name}}', must be one of #{allowed_values}."; $invalid_properties[] = "invalid value for '{{name}}', must be one of #{allowed_values}.";
} }
{{/isEnum}} {{/isEnum}}
{{#hasValidation}} {{#hasValidation}}
{{#maxLength}} {{#maxLength}}
if (strlen($this->container['{{name}}']) > {{maxLength}}) { if (strlen($this->container['{{name}}']) > {{maxLength}}) {
$invalid_properties[] = "invalid value for '${{name}}', the character length must be smaller than or equal to {{{maxLength}}}."; $invalid_properties[] = "invalid value for '{{name}}', the character length must be smaller than or equal to {{{maxLength}}}.";
} }
{{/maxLength}} {{/maxLength}}
{{#minLength}} {{#minLength}}
if (strlen($this->container['{{name}}']) < {{minLength}}) { if (strlen($this->container['{{name}}']) < {{minLength}}) {
$invalid_properties[] = "invalid value for '${{name}}', the character length must be bigger than or equal to {{{minLength}}}."; $invalid_properties[] = "invalid value for '{{name}}', the character length must be bigger than or equal to {{{minLength}}}.";
} }
{{/minLength}} {{/minLength}}
{{#maximum}} {{#maximum}}
if ($this->container['{{name}}'] > {{maximum}}) { if ($this->container['{{name}}'] > {{maximum}}) {
$invalid_properties[] = "invalid value for '${{name}}', must be smaller than or equal to {{maximum}}."; $invalid_properties[] = "invalid value for '{{name}}', must be smaller than or equal to {{maximum}}.";
} }
{{/maximum}} {{/maximum}}
{{#minimum}} {{#minimum}}
if ($this->container['{{name}}'] < {{minimum}}) { if ($this->container['{{name}}'] < {{minimum}}) {
$invalid_properties[] = "invalid value for '${{name}}', must be bigger than or equal to {{minimum}}."; $invalid_properties[] = "invalid value for '{{name}}', must be bigger than or equal to {{minimum}}.";
} }
{{/minimum}} {{/minimum}}
{{#pattern}} {{#pattern}}
if (!preg_match("{{pattern}}", $this->container['{{name}}'])) { if (!preg_match("{{pattern}}", $this->container['{{name}}'])) {
$invalid_properties[] = "invalid value for '${{name}}', must be conform to the pattern {{pattern}}."; $invalid_properties[] = "invalid value for '{{name}}', must be conform to the pattern {{pattern}}.";
} }
{{/pattern}} {{/pattern}}
{{/hasValidation}} {{/hasValidation}}
@ -265,7 +272,7 @@ class {{classname}} {{#parentSchema}}extends {{{parent}}} {{/parentSchema}}imple
/** /**
* Sets {{name}} * Sets {{name}}
* @param {{datatype}} ${{name}} {{#description}}{{{description}}}{{/description}} * @param {{datatype}} ${{name}}{{#description}} {{{description}}}{{/description}}
* @return $this * @return $this
*/ */
public function {{setter}}(${{name}}) public function {{setter}}(${{name}})

View File

@ -7,7 +7,8 @@ class {{classname}} {
* Gets allowable values of the enum * Gets allowable values of the enum
* @return string[] * @return string[]
*/ */
public function {{getter}}AllowableValues() { public function {{getter}}AllowableValues()
{
return [ return [
{{#allowableValues}}{{#enumVars}}self::{{datatypeWithEnum}}_{{{name}}},{{^-last}} {{#allowableValues}}{{#enumVars}}self::{{datatypeWithEnum}}_{{{name}}},{{^-last}}
{{/-last}}{{/enumVars}}{{/allowableValues}} {{/-last}}{{/enumVars}}{{/allowableValues}}

View File

@ -9,7 +9,8 @@ class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}implements ArrayA
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
static function swaggerTypes() { static function swaggerTypes()
{
return self::$swaggerTypes{{#parent}} + parent::swaggerTypes(){{/parent}}; return self::$swaggerTypes{{#parent}} + parent::swaggerTypes(){{/parent}};
} }
@ -22,7 +23,8 @@ class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}implements ArrayA
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
static function attributeMap() { static function attributeMap()
{
return {{#parent}}parent::attributeMap() + {{/parent}}self::$attributeMap; return {{#parent}}parent::attributeMap() + {{/parent}}self::$attributeMap;
} }
@ -35,7 +37,8 @@ class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}implements ArrayA
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
static function setters() { static function setters()
{
return {{#parent}}parent::setters() + {{/parent}}self::$setters; return {{#parent}}parent::setters() + {{/parent}}self::$setters;
} }
@ -48,7 +51,8 @@ class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}implements ArrayA
{{/hasMore}}{{/vars}} {{/hasMore}}{{/vars}}
); );
static function getters() { static function getters()
{
return {{#parent}}parent::getters() + {{/parent}}self::$getters; return {{#parent}}parent::getters() + {{/parent}}self::$getters;
} }
@ -60,7 +64,8 @@ class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}implements ArrayA
* Gets allowable values of the enum * Gets allowable values of the enum
* @return string[] * @return string[]
*/ */
public function {{getter}}AllowableValues() { public function {{getter}}AllowableValues()
{
return [ return [
{{#allowableValues}}{{#enumVars}}self::{{datatypeWithEnum}}_{{{name}}},{{^-last}} {{#allowableValues}}{{#enumVars}}self::{{datatypeWithEnum}}_{{{name}}},{{^-last}}
{{/-last}}{{/enumVars}}{{/allowableValues}} {{/-last}}{{/enumVars}}{{/allowableValues}}

View File

@ -39,7 +39,7 @@ namespace {{modelPackage}};
* {{classname}}Test Class Doc Comment * {{classname}}Test Class Doc Comment
* *
* @category Class * @category Class
* @description {{description}} * @description {{#description}}{{description}}{{/description}}{{^description}}{{classname}}{{/description}}
* @package {{invokerPackage}} * @package {{invokerPackage}}
* @author http://github.com/swagger-api/swagger-codegen * @author http://github.com/swagger-api/swagger-codegen
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
@ -51,24 +51,26 @@ class {{classname}}Test extends \PHPUnit_Framework_TestCase
/** /**
* Setup before running each test case * Setup before running each test case
*/ */
public static function setUpBeforeClass() { public static function setUpBeforeClass()
{
} }
/** /**
* Clean up after running each test case * Clean up after running each test case
*/ */
public static function tearDownAfterClass() { public static function tearDownAfterClass()
{
} }
/** /**
* Test {{classname}} * Test "{{classname}}"
*/ */
public function test{{classname}}() { public function test{{classname}}()
{
} }
} }
{{/model}} {{/model}}
{{/models}} {{/models}}

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body>
<!-- This file lives in public/404.html -->
<div class="dialog">
<div>
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<title>The change you wanted was rejected (422)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body>
<!-- This file lives in public/422.html -->
<div class="dialog">
<div>
<h1>The change you wanted was rejected.</h1>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>We're sorry, but something went wrong (500)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body>
<!-- This file lives in public/500.html -->
<div class="dialog">
<div>
<h1>We're sorry, but something went wrong.</h1>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

View File

@ -0,0 +1,36 @@
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '>= 5.0.0.racecar1', '< 5.1'
# Use mysql as the database for Active Record
gem 'mysql2', '>= 0.3.18', '< 0.5'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
# gem 'rack-cors'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platform: :mri
end
group :development do
gem 'listen', '~> 3.0.5'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

View File

@ -0,0 +1,25 @@
# Swagger for Rails 5
This is a project to provide Swagger support inside the [Sinatra](http://rubyonrails.org/) framework.
## Prerequisites
You need to install ruby >= 2.2.2 and run:
```
bundle install
```
## Getting started
This sample was generated with the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project.
```
bin/rake db:create
bin/rails s
```
To list all your routes, use:
```
bin/rake routes
```

View File

@ -0,0 +1,6 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require_relative 'config/application'
Rails.application.load_tasks

View File

@ -0,0 +1,6 @@
# Be sure to restart your server when you modify this file.
# Require `belongs_to` associations by default. This is a new Rails 5.0
# default, so it is introduced as a configuration option to ensure that apps
# made on earlier versions of Rails are not affected when upgrading.
Rails.application.config.active_record.belongs_to_required_by_default = true

View File

@ -0,0 +1,30 @@
require_relative 'boot'
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module ApiDemo
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
# Skip views, helpers and assets when generating a new resource.
config.api_only = true
end
end

View File

@ -0,0 +1,2 @@
class ApplicationController < ActionController::API
end

View File

@ -0,0 +1,6 @@
# Be sure to restart your server when you modify this file.
# ApplicationController.renderer.defaults.merge!(
# http_host: 'example.org',
# https: false
# )

View File

@ -0,0 +1,2 @@
class ApplicationJob < ActiveJob::Base
end

View File

@ -0,0 +1,4 @@
class ApplicationMailer < ActionMailer::Base
default from: 'from@example.com'
layout 'mailer'
end

View File

@ -0,0 +1,3 @@
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end

View File

@ -0,0 +1,7 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!

View File

@ -0,0 +1,3 @@
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' # Set up gems listed in the Gemfile.

View File

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
load Gem.bin_path('bundler', 'bundle')

View File

@ -0,0 +1,10 @@
# Action Cable uses Redis by default to administer connections, channels, and sending/receiving messages over the WebSocket.
production:
adapter: redis
url: redis://localhost:6379/1
development:
adapter: async
test:
adapter: async

View File

@ -0,0 +1,6 @@
# Be sure to restart your server when you modify this file.
# Do not halt callback chains when a callback returns false. This is a new
# Rails 5.0 default, so it is introduced as a configuration option to ensure
# that apps made with earlier versions of Rails are not affected when upgrading.
ActiveSupport.halt_callback_chains_on_return_false = false

View File

@ -0,0 +1,5 @@
# Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end

View File

@ -0,0 +1,5 @@
# This file is used by Rack-based servers to start the application.
require_relative 'config/environment'
run Rails.application

View File

@ -0,0 +1,5 @@
# Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
module ApplicationCable
class Connection < ActionCable::Connection::Base
end
end

View File

@ -0,0 +1,49 @@
class {{classname}} < ApplicationController
{{#operations}}
{{#operation}}
{{#isRestfulIndex}}
def index
# Your code here
render json: {"message" => "yes, it worked"}
end
{{/isRestfulIndex}}
{{#isRestfulShow}}
def show
# Your code here
render json: {"message" => "yes, it worked"}
end
{{/isRestfulShow}}
{{#isRestfulCreate}}
def create
# Your code here
render json: {"message" => "yes, it worked"}
end
{{/isRestfulCreate}}
{{#isRestfulUpdate}}
def update
# Your code here
render json: {"message" => "yes, it worked"}
end
{{/isRestfulUpdate}}
{{#isRestfulDestroy}}
def destroy
# Your code here
render json: {"message" => "yes, it worked"}
end
{{/isRestfulDestroy}}
{{^isRestful}}
def {{nickname}}
# Your code here
render json: {"message" => "yes, it worked"}
end
{{/isRestful}}
{{/operation}}
{{/operations}}
end

View File

@ -0,0 +1,16 @@
# Be sure to restart your server when you modify this file.
# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
# Read more: https://github.com/cyu/rack-cors
# Rails.application.config.middleware.insert_before 0, Rack::Cors do
# allow do
# origins 'example.com'
#
# resource '*',
# headers: :any,
# methods: [:get, :post, :put, :patch, :delete, :options, :head]
# end
# end

View File

@ -0,0 +1,54 @@
# MySQL. Versions 5.0 and up are supported.
#
# Install the MySQL driver
# gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
# gem 'mysql2'
#
# And be sure to use new-style password hashing:
# http://dev.mysql.com/doc/refman/5.7/en/old-client.html
#
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password:
socket: /tmp/mysql.sock
development:
<<: *default
database: api_demo_development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: api_demo_test
# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
# DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
# production:
# url: <%= ENV['DATABASE_URL'] %>
#
production:
<<: *default
database: api_demo_production
username: api_demo
password: <%= ENV['API_DEMO_DATABASE_PASSWORD'] %>

View File

@ -0,0 +1,47 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports.
config.consider_all_requests_local = true
# Enable/disable caching. By default caching is disabled.
if Rails.root.join('tmp/caching-dev.txt').exist?
config.action_controller.perform_caching = true
config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => 'public, max-age=172800'
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_caching = false
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
# Use an evented file watcher to asynchronously detect changes in source code,
# routes, locales, etc. This feature depends on the listen gem.
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
end

View File

@ -0,0 +1,23 @@
# Files in the config/locales directory are used for internationalization
# and are automatically loaded by Rails. If you want to use locales other
# than English, add the necessary files in this directory.
#
# To use the locales, use `I18n.t`:
#
# I18n.t 'hello'
#
# In views, this is aliased to just `t`:
#
# <%= t('hello') %>
#
# To use a different locale, set it with `I18n.locale`:
#
# I18n.locale = :es
#
# This would use the information in config/locales/es.yml.
#
# To learn more, please read the Rails Internationalization guide
# available at http://guides.rubyonrails.org/i18n.html.
en:
hello: "Hello world"

View File

@ -0,0 +1,5 @@
# Load the Rails application.
require_relative 'application'
# Initialize the Rails application.
Rails.application.initialize!

View File

@ -0,0 +1,4 @@
# Be sure to restart your server when you modify this file.
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password]

View File

@ -0,0 +1,16 @@
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
# end

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
/* Email styles need to be inline */
</style>
</head>
<body>
<%= yield %>
</body>
</html>

View File

@ -0,0 +1 @@
<%= yield %>

View File

@ -0,0 +1,4 @@
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf

View File

@ -0,0 +1,80 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Action Cable endpoint configuration
# config.action_cable.url = 'wss://example.com/cable'
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
# Don't mount Action Cable in the main server process.
# config.action_cable.mount_path = nil
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :debug
# Prepend all log lines with the following tags.
config.log_tags = [ :request_id ]
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Use a real queuing backend for Active Job (and separate queues per environment)
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "api_demo_#{Rails.env}"
config.action_mailer.perform_caching = false
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Use a different logger for distributed setups.
# require 'syslog/logger'
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
if ENV["RAILS_LOG_TO_STDOUT"].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
end

View File

@ -0,0 +1,47 @@
# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum, this matches the default thread size of Active Record.
#
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
# Specifies the `port` that Puma will listen on to receive requests, default is 3000.
#
port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory. If you use this option
# you need to make sure to reconnect any threads in the `on_worker_boot`
# block.
#
# preload_app!
# The code in the `on_worker_boot` will be called if you are using
# clustered mode by specifying a number of `workers`. After each worker
# process is booted this block will be run, if you are using `preload_app!`
# option you will want to use this block to reconnect to any threads
# or connections that may have been created at application boot, Ruby
# cannot share connections between processes.
#
# on_worker_boot do
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
# end
# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

View File

@ -0,0 +1,4 @@
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'rails/commands'

Some files were not shown because too many files have changed in this diff Show More