diff --git a/CI/samples.ci/client/petstore/typescript-fetch/builds/default/pom.xml b/CI/samples.ci/client/petstore/typescript-fetch/builds/default/pom.xml
new file mode 100644
index 000000000000..b40b83a0c751
--- /dev/null
+++ b/CI/samples.ci/client/petstore/typescript-fetch/builds/default/pom.xml
@@ -0,0 +1,26 @@
+
+ 4.0.0
+ org.openapitools
+ TypeScriptAngularBuildPestoreClientTests
+ pom
+ 1.0-SNAPSHOT
+ TS Fetch Default Petstore Client
+
+
+
+ maven-dependency-plugin
+
+
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}
+
+
+
+
+
+
+
diff --git a/CI/samples.ci/client/petstore/typescript-fetch/builds/es6-target/pom.xml b/CI/samples.ci/client/petstore/typescript-fetch/builds/es6-target/pom.xml
new file mode 100644
index 000000000000..db6dfdfeb6aa
--- /dev/null
+++ b/CI/samples.ci/client/petstore/typescript-fetch/builds/es6-target/pom.xml
@@ -0,0 +1,59 @@
+
+ 4.0.0
+ org.openapitools
+ TypeScriptAngularBuildES6PestoreClientTests
+ pom
+ 1.0-SNAPSHOT
+ TS Fetch ES6 Petstore Client
+
+
+
+ maven-dependency-plugin
+
+
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.2.1
+
+
+ npm-install
+ integration-test
+
+ exec
+
+
+ npm
+
+ install
+
+
+
+
+ npm-test
+ integration-test
+
+ exec
+
+
+ npm
+
+ test
+
+
+
+
+
+
+
+
diff --git a/CI/samples.ci/client/petstore/typescript-fetch/builds/with-npm-version/pom.xml b/CI/samples.ci/client/petstore/typescript-fetch/builds/with-npm-version/pom.xml
new file mode 100644
index 000000000000..339fe7665186
--- /dev/null
+++ b/CI/samples.ci/client/petstore/typescript-fetch/builds/with-npm-version/pom.xml
@@ -0,0 +1,73 @@
+
+ 4.0.0
+ org.openapitools
+ TypeScriptAngularBuildWithNPMVersionPestoreClientTests
+ pom
+ 1.0-SNAPSHOT
+ TS Fetch Petstore Client (with npm)
+
+
+
+ maven-dependency-plugin
+
+
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.2.1
+
+
+ npm-install
+ integration-test
+
+ exec
+
+
+ npm
+
+ install
+
+
+
+
+ npm-build
+ integration-test
+
+ exec
+
+
+ npm
+
+ run
+ build
+
+
+
+
+ npm-test
+ integration-test
+
+ exec
+
+
+ npm
+
+ test
+
+
+
+
+
+
+
+
diff --git a/CI/samples.ci/client/petstore/typescript-fetch/tests/default/pom.xml b/CI/samples.ci/client/petstore/typescript-fetch/tests/default/pom.xml
new file mode 100644
index 000000000000..92063ea7bcc5
--- /dev/null
+++ b/CI/samples.ci/client/petstore/typescript-fetch/tests/default/pom.xml
@@ -0,0 +1,59 @@
+
+ 4.0.0
+ org.openapitools
+ TypeScriptFetchPestoreClientTests
+ pom
+ 1.0-SNAPSHOT
+ TS Fetch Petstore Test Client
+
+
+
+ maven-dependency-plugin
+
+
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.2.1
+
+
+ npm-install
+ pre-integration-test
+
+ exec
+
+
+ npm
+
+ install
+
+
+
+
+ npm-test
+ integration-test
+
+ exec
+
+
+ npm
+
+ test
+
+
+
+
+
+
+
+
diff --git a/CI/samples/client/petstore/csharp/OpenAPIClient/src/Org.OpenAPITools.Test/obj/Debug/Org.OpenAPITools.Test.csproj.CoreCompileInputs.cache b/CI/samples/client/petstore/csharp/OpenAPIClient/src/Org.OpenAPITools.Test/obj/Debug/Org.OpenAPITools.Test.csproj.CoreCompileInputs.cache
new file mode 100644
index 000000000000..4096123585d5
--- /dev/null
+++ b/CI/samples/client/petstore/csharp/OpenAPIClient/src/Org.OpenAPITools.Test/obj/Debug/Org.OpenAPITools.Test.csproj.CoreCompileInputs.cache
@@ -0,0 +1 @@
+c2fcc2ae9693a8e8d02b25e286844aad88188fcb
diff --git a/CI/samples/client/petstore/csharp/OpenAPIClient/src/Org.OpenAPITools.Test/obj/Debug/Org.OpenAPITools.Test.csprojResolveAssemblyReference.cache b/CI/samples/client/petstore/csharp/OpenAPIClient/src/Org.OpenAPITools.Test/obj/Debug/Org.OpenAPITools.Test.csprojResolveAssemblyReference.cache
new file mode 100644
index 000000000000..76cdea6cfa73
Binary files /dev/null and b/CI/samples/client/petstore/csharp/OpenAPIClient/src/Org.OpenAPITools.Test/obj/Debug/Org.OpenAPITools.Test.csprojResolveAssemblyReference.cache differ
diff --git a/bin/typescript-fetch-petstore-target-es6.sh b/bin/typescript-fetch-petstore-target-es6.sh
index 9abb1598b9f9..755fb4c7cc85 100755
--- a/bin/typescript-fetch-petstore-target-es6.sh
+++ b/bin/typescript-fetch-petstore-target-es6.sh
@@ -30,3 +30,5 @@ export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/
ags="generate -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g 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
+cp CI/samples.ci/client/petstore/typescript-fetch/builds/es6-target/pom.xml samples/client/petstore/typescript-fetch/builds/es6-target/pom.xml
+cp CI/samples.ci/client/petstore/typescript-fetch/tests/default/pom.xml samples/client/petstore/typescript-fetch/tests/default/pom.xml
\ No newline at end of file
diff --git a/bin/typescript-fetch-petstore-with-npm-version.sh b/bin/typescript-fetch-petstore-with-npm-version.sh
index ab540f271f15..4e604b9b88eb 100755
--- a/bin/typescript-fetch-petstore-with-npm-version.sh
+++ b/bin/typescript-fetch-petstore-with-npm-version.sh
@@ -30,3 +30,5 @@ export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/
ags="generate -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g 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
+cp CI/samples.ci/client/petstore/typescript-fetch/builds/with-npm-version/pom.xml samples/client/petstore/typescript-fetch/builds/with-npm-version/pom.xml
+cp CI/samples.ci/client/petstore/typescript-fetch/tests/default/pom.xml samples/client/petstore/typescript-fetch/tests/default/pom.xml
\ No newline at end of file
diff --git a/bin/typescript-fetch-petstore.sh b/bin/typescript-fetch-petstore.sh
index 8cdf91ef5940..e2a9d85f4d62 100755
--- a/bin/typescript-fetch-petstore.sh
+++ b/bin/typescript-fetch-petstore.sh
@@ -30,3 +30,5 @@ export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/
ags="generate -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g typescript-fetch -o samples/client/petstore/typescript-fetch/builds/default $@"
java $JAVA_OPTS -jar $executable $ags
+cp CI/samples.ci/client/petstore/typescript-fetch/builds/default/pom.xml samples/client/petstore/typescript-fetch/builds/default/pom.xml
+cp CI/samples.ci/client/petstore/typescript-fetch/tests/default/pom.xml samples/client/petstore/typescript-fetch/tests/default/pom.xml
\ No newline at end of file
diff --git a/modules/openapi-generator-gradle-plugin/bin/main/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt b/modules/openapi-generator-gradle-plugin/bin/main/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt
new file mode 100644
index 000000000000..b4a2089c11bb
--- /dev/null
+++ b/modules/openapi-generator-gradle-plugin/bin/main/org/openapitools/generator/gradle/plugin/OpenApiGeneratorPlugin.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openapitools.generator.gradle.plugin
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.invoke
+import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorGenerateExtension
+import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorMetaExtension
+import org.openapitools.generator.gradle.plugin.extensions.OpenApiGeneratorValidateExtension
+import org.openapitools.generator.gradle.plugin.tasks.GenerateTask
+import org.openapitools.generator.gradle.plugin.tasks.GeneratorsTask
+import org.openapitools.generator.gradle.plugin.tasks.MetaTask
+import org.openapitools.generator.gradle.plugin.tasks.ValidateTask
+
+/**
+ * A plugin providing common Open API Generator use cases.
+ *
+ * @author Jim Schubert
+ */
+@Suppress("unused")
+class OpenApiGeneratorPlugin : Plugin {
+ override fun apply(project: Project) {
+ project.run {
+ val meta = extensions.create(
+ "openApiMeta",
+ OpenApiGeneratorMetaExtension::class.java,
+ project
+ )
+
+ val validate = extensions.create(
+ "openApiValidate",
+ OpenApiGeneratorValidateExtension::class.java,
+ project
+ )
+
+ val generate = extensions.create(
+ "openApiGenerate",
+ OpenApiGeneratorGenerateExtension::class.java,
+ project
+ )
+
+ generate.outputDir.set("$buildDir/generate-resources/main")
+
+ tasks {
+ "openApiGenerators"(GeneratorsTask::class) {
+ group = pluginGroup
+ description = "Lists generators available via Open API Generators."
+ }
+ "openApiMeta"(MetaTask::class) {
+ group = pluginGroup
+ description = "Generates a new generator to be consumed via Open API Generator."
+
+ generatorName.set(meta.generatorName)
+ packageName.set(meta.packageName)
+ outputFolder.set(meta.outputFolder)
+ }
+ "openApiValidate"(ValidateTask::class) {
+ group = pluginGroup
+ description = "Validates an Open API 2.0 or 3.x specification document."
+
+ inputSpec.set(validate.inputSpec)
+ }
+ "openApiGenerate"(GenerateTask::class) {
+ group = pluginGroup
+ description = "Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents."
+
+ verbose.set(generate.verbose)
+ validateSpec.set(generate.validateSpec)
+ generatorName.set(generate.generatorName)
+ outputDir.set(generate.outputDir)
+ inputSpec.set(generate.inputSpec)
+ templateDir.set(generate.templateDir)
+ auth.set(generate.auth)
+ systemProperties.set(generate.systemProperties)
+ configFile.set(generate.configFile)
+ skipOverwrite.set(generate.skipOverwrite)
+ apiPackage.set(generate.apiPackage)
+ modelPackage.set(generate.modelPackage)
+ modelNamePrefix.set(generate.modelNamePrefix)
+ modelNameSuffix.set(generate.modelNameSuffix)
+ instantiationTypes.set(generate.instantiationTypes)
+ typeMappings.set(generate.typeMappings)
+ additionalProperties.set(generate.additionalProperties)
+ languageSpecificPrimitives.set(generate.languageSpecificPrimitives)
+ importMappings.set(generate.importMappings)
+ invokerPackage.set(generate.invokerPackage)
+ groupId.set(generate.groupId)
+ id.set(generate.id)
+ version.set(generate.version)
+ library.set(generate.library)
+ gitUserId.set(generate.gitUserId)
+ gitRepoId.set(generate.gitRepoId)
+ releaseNote.set(generate.releaseNote)
+ httpUserAgent.set(generate.httpUserAgent)
+ reservedWordsMappings.set(generate.reservedWordsMappings)
+ ignoreFileOverride.set(generate.ignoreFileOverride)
+ removeOperationIdPrefix.set(generate.removeOperationIdPrefix)
+ apiFilesConstrainedTo.set(generate.apiFilesConstrainedTo)
+ modelFilesConstrainedTo.set(generate.modelFilesConstrainedTo)
+ supportingFilesConstrainedTo.set(generate.supportingFilesConstrainedTo)
+ generateModelTests.set(generate.generateModelTests)
+ generateModelDocumentation.set(generate.generateModelDocumentation)
+ generateApiTests.set(generate.generateApiTests)
+ generateApiDocumentation.set(generate.generateApiDocumentation)
+ withXml.set(generate.withXml)
+ configOptions.set(generate.configOptions)
+ }
+ }
+ }
+ }
+
+ companion object {
+ const val pluginGroup = "OpenAPI Tools"
+ }
+}
+
diff --git a/modules/openapi-generator-gradle-plugin/bin/main/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt b/modules/openapi-generator-gradle-plugin/bin/main/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt
new file mode 100644
index 000000000000..fa7726542ccb
--- /dev/null
+++ b/modules/openapi-generator-gradle-plugin/bin/main/org/openapitools/generator/gradle/plugin/extensions/OpenApiGeneratorGenerateExtension.kt
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openapitools.generator.gradle.plugin.extensions
+
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.listProperty
+import org.gradle.kotlin.dsl.property
+
+/**
+ * Gradle project level extension object definition for the generate task
+ *
+ * @author Jim Schubert
+ */
+open class OpenApiGeneratorGenerateExtension(project: Project) {
+
+ /**
+ * The verbosity of generation
+ */
+ val verbose = project.objects.property()
+
+ /**
+ * Whether or not an input specification should be validated upon generation.
+ */
+ val validateSpec = project.objects.property()
+
+ /**
+ * The name of the generator which will handle codegen. (see "openApiGenerators" task)
+ */
+ val generatorName = project.objects.property()
+
+ /**
+ * The output target directory into which code will be generated.
+ */
+ val outputDir = project.objects.property()
+
+ /**
+ * The Open API 2.0/3.x specification location.
+ */
+ val inputSpec = project.objects.property()
+
+ /**
+ * The template directory holding a custom template.
+ */
+ val templateDir = project.objects.property()
+
+ /**
+ * Adds authorization headers when fetching the OpenAPI definitions remotely.
+ * Pass in a URL-encoded string of name:header with a comma separating multiple values
+ */
+ val auth = project.objects.property()
+
+ /**
+ * Sets specified system properties.
+ */
+ val systemProperties = project.objects.property