Skip to content

Commit e99acb8

Browse files
committed
added new generator and templates for typescript axios
1 parent b7acec3 commit e99acb8

21 files changed

+945
-0
lines changed
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package io.swagger.codegen.v3.generators.typescript;
2+
3+
import io.swagger.codegen.v3.CodegenConstants;
4+
import io.swagger.codegen.v3.CodegenModel;
5+
import io.swagger.codegen.v3.CodegenOperation;
6+
import io.swagger.codegen.v3.CodegenProperty;
7+
import io.swagger.codegen.v3.SupportingFile;
8+
import org.apache.commons.lang3.StringUtils;
9+
10+
import java.util.ArrayList;
11+
import java.util.HashMap;
12+
import java.util.List;
13+
import java.util.Locale;
14+
import java.util.Map;
15+
import java.util.TreeSet;
16+
17+
import static io.swagger.codegen.v3.generators.handlebars.ExtensionHelper.getBooleanValue;
18+
19+
public class TypeScriptAxiosClientCodegen extends AbstractTypeScriptClientCodegen {
20+
21+
public static final String NPM_NAME = "npmName";
22+
public static final String NPM_REPOSITORY = "npmRepository";
23+
public static final String DEFAULT_API_PACKAGE = "apis";
24+
public static final String DEFAULT_MODEL_PACKAGE = "models";
25+
26+
protected String npmRepository = null;
27+
28+
private String tsModelPackage = "";
29+
30+
public TypeScriptAxiosClientCodegen() {
31+
super();
32+
importMapping.clear();
33+
outputFolder = "generated-code/typescript-axios";
34+
}
35+
36+
@Override
37+
public String getName() {
38+
return "typescript-axios";
39+
}
40+
41+
@Override
42+
public String getHelp() {
43+
return "Generates a TypeScript Axios client library.";
44+
}
45+
46+
public String getNpmRepository() {
47+
return npmRepository;
48+
}
49+
50+
public void setNpmRepository(String npmRepository) {
51+
this.npmRepository = npmRepository;
52+
}
53+
54+
private static String getRelativeToRoot(String path) {
55+
StringBuilder sb = new StringBuilder();
56+
int slashCount = path.split("/").length;
57+
if (slashCount == 0) {
58+
sb.append("./");
59+
} else {
60+
for (int i = 0; i < slashCount; ++i) {
61+
sb.append("../");
62+
}
63+
}
64+
return sb.toString();
65+
}
66+
67+
@Override
68+
public void processOpts() {
69+
super.processOpts();
70+
if (StringUtils.isBlank(modelPackage)) {
71+
modelPackage = DEFAULT_MODEL_PACKAGE;
72+
}
73+
if (StringUtils.isBlank(apiPackage)) {
74+
apiPackage = DEFAULT_API_PACKAGE;
75+
}
76+
tsModelPackage = modelPackage.replaceAll("\\.", "/");
77+
String tsApiPackage = apiPackage.replaceAll("\\.", "/");
78+
79+
String modelRelativeToRoot = getRelativeToRoot(tsModelPackage);
80+
String apiRelativeToRoot = getRelativeToRoot(tsApiPackage);
81+
82+
additionalProperties.put("tsModelPackage", tsModelPackage);
83+
additionalProperties.put("tsApiPackage", tsApiPackage);
84+
additionalProperties.put("apiRelativeToRoot", apiRelativeToRoot);
85+
additionalProperties.put("modelRelativeToRoot", modelRelativeToRoot);
86+
87+
supportingFiles.add(new SupportingFile("index.mustache", "", "index.ts"));
88+
supportingFiles.add(new SupportingFile("baseApi.mustache", "", "base.ts"));
89+
supportingFiles.add(new SupportingFile("api.mustache", "", "api.ts"));
90+
supportingFiles.add(new SupportingFile("configuration.mustache", "", "configuration.ts"));
91+
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
92+
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
93+
supportingFiles.add(new SupportingFile("npmignore", "", ".npmignore"));
94+
95+
modelTemplateFiles.put("model.mustache", ".ts");
96+
apiTemplateFiles.put("apiInner.mustache", ".ts");
97+
supportingFiles.add(new SupportingFile("modelIndex.mustache", tsModelPackage, "index.ts"));
98+
99+
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
100+
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
101+
supportingFiles.add(new SupportingFile("tsconfig.mustache", "", "tsconfig.json"));
102+
}
103+
104+
@Override
105+
public Map<String, Object> postProcessOperations(Map<String, Object> operations) {
106+
boolean hasImports = operations.get("hasImport") != null && Boolean.parseBoolean(operations.get("hasImport").toString());
107+
if (hasImports) {
108+
List<Map<String, String>> imports = (List<Map<String, String>>) operations.get("imports");
109+
110+
for (Map<String, String> importMap : imports) {
111+
final String importValue = importMap.get("import");
112+
if (StringUtils.isNotBlank(importValue) && importValue.contains(".")) {
113+
int index = importValue.indexOf(".");
114+
importMap.put("import", importValue.substring(index + 1));
115+
}
116+
}
117+
}
118+
return operations;
119+
}
120+
121+
@Override
122+
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
123+
objs = super.postProcessOperationsWithModels(objs, allModels);
124+
Map<String, Object> vals = (Map<String, Object>) objs.getOrDefault("operations", new HashMap<>());
125+
List<CodegenOperation> operations = (List<CodegenOperation>) vals.getOrDefault("operation", new ArrayList<>());
126+
/*
127+
Filter all the operations that are multipart/form-data operations and set the vendor extension flag
128+
'multipartFormData' for the template to work with.
129+
*/
130+
operations.stream()
131+
.filter(op -> getBooleanValue(op, CodegenConstants.HAS_CONSUMES_EXT_NAME))
132+
.filter(op -> op.consumes.stream().anyMatch(opc -> opc.values().stream().anyMatch("multipart/form-data"::equals)))
133+
.forEach(op -> op.vendorExtensions.putIfAbsent("multipartFormData", true));
134+
return objs;
135+
}
136+
137+
@Override
138+
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
139+
Map<String, Object> result = super.postProcessAllModels(objs);
140+
for (Map.Entry<String, Object> entry : result.entrySet()) {
141+
Map<String, Object> inner = (Map<String, Object>) entry.getValue();
142+
List<Map<String, Object>> models = (List<Map<String, Object>>) inner.get("models");
143+
for (Map<String, Object> model : models) {
144+
CodegenModel codegenModel = (CodegenModel) model.get("model");
145+
//todo: model.put("hasAllOf", codegenModel.allOf.size() > 0);
146+
//todo: model.put("hasOneOf", codegenModel.oneOf.size() > 0);
147+
}
148+
}
149+
return result;
150+
}
151+
152+
153+
@Override
154+
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
155+
List<Object> models = (List<Object>) postProcessModelsEnum(objs).get("models");
156+
157+
for (Object _mo : models) {
158+
Map<String, Object> mo = (Map<String, Object>) _mo;
159+
CodegenModel cm = (CodegenModel) mo.get("model");
160+
161+
// Deduce the model file name in kebab case
162+
cm.classFilename = cm.classname.replaceAll("([a-z0-9])([A-Z])", "$1-$2").toLowerCase(Locale.ROOT);
163+
164+
//processed enum names
165+
cm.imports = new TreeSet(cm.imports);
166+
// name enum with model name, e.g. StatusEnum => PetStatusEnum
167+
for (CodegenProperty var : cm.vars) {
168+
if (getBooleanValue(var, CodegenConstants.IS_ENUM_EXT_NAME)) {
169+
var.datatypeWithEnum = var.datatypeWithEnum.replace(var.enumName, cm.classname + var.enumName);
170+
var.enumName = var.enumName.replace(var.enumName, cm.classname + var.enumName);
171+
}
172+
}
173+
if (cm.parent != null) {
174+
for (CodegenProperty var : cm.allVars) {
175+
if (getBooleanValue(var, CodegenConstants.IS_ENUM_EXT_NAME)) {
176+
var.datatypeWithEnum = var.datatypeWithEnum.replace(var.enumName, cm.classname + var.enumName);
177+
var.enumName = var.enumName.replace(var.enumName, cm.classname + var.enumName);
178+
}
179+
}
180+
}
181+
}
182+
183+
// Apply the model file name to the imports as well
184+
for (Map<String, String> m : (List<Map<String, String>>) objs.get("imports")) {
185+
String javaImport = m.get("import").substring(modelPackage.length() + 1);
186+
String tsImport = tsModelPackage + "/" + javaImport;
187+
m.put("tsImport", tsImport);
188+
m.put("class", javaImport);
189+
m.put("filename", javaImport.replaceAll("([a-z0-9])([A-Z])", "$1-$2").toLowerCase(Locale.ROOT));
190+
}
191+
return objs;
192+
}
193+
194+
/**
195+
* Overriding toRegularExpression() to avoid escapeText() being called,
196+
* as it would return a broken regular expression if any escaped character / metacharacter were present.
197+
*/
198+
@Override
199+
public String toRegularExpression(String pattern) {
200+
return addRegularExpressionDelimiter(pattern);
201+
}
202+
203+
@Override
204+
public String toModelFilename(String name) {
205+
return super.toModelFilename(name).replaceAll("([a-z0-9])([A-Z])", "$1-$2").toLowerCase(Locale.ROOT);
206+
}
207+
208+
@Override
209+
public String toApiFilename(String name) {
210+
return super.toApiFilename(name).replaceAll("([a-z0-9])([A-Z])", "$1-$2").toLowerCase(Locale.ROOT);
211+
}
212+
213+
@Override
214+
public String getDefaultTemplateDir() {
215+
return "typescript-axios";
216+
}
217+
}

src/main/resources/META-INF/services/io.swagger.codegen.v3.CodegenConfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ io.swagger.codegen.v3.generators.swift.Swift3Codegen
3434
io.swagger.codegen.v3.generators.swift.Swift4Codegen
3535
io.swagger.codegen.v3.generators.swift.Swift5Codegen
3636
io.swagger.codegen.v3.generators.typescript.TypeScriptAngularClientCodegen
37+
io.swagger.codegen.v3.generators.typescript.TypeScriptAxiosClientCodegen
3738
io.swagger.codegen.v3.generators.typescript.TypeScriptFetchClientCodegen
3839
io.swagger.codegen.v3.generators.javascript.JavaScriptClientCodegen
8 KB
Binary file not shown.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
## {{npmName}}@{{npmVersion}}
2+
3+
This generator creates TypeScript/JavaScript client that utilizes [axios](https://github.com/axios/axios). The generated Node module can be used in the following environments:
4+
5+
Environment
6+
* Node.js
7+
* Webpack
8+
* Browserify
9+
10+
Language level
11+
* ES5 - you must have a Promises/A+ library installed
12+
* ES6
13+
14+
Module system
15+
* CommonJS
16+
* ES6 module system
17+
18+
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))
19+
20+
### Building
21+
22+
To build and compile the typescript sources to javascript use:
23+
```
24+
npm install
25+
npm run build
26+
```
27+
28+
### Publishing
29+
30+
First build the package then run ```npm publish```
31+
32+
### Consuming
33+
34+
navigate to the folder of your consuming project and run one of the following commands.
35+
36+
_published:_
37+
38+
```
39+
npm install {{npmName}}@{{npmVersion}} --save
40+
```
41+
42+
_unPublished (not recommended):_
43+
44+
```
45+
npm install PATH_TO_GENERATED_PACKAGE --save
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* tslint:disable */
2+
/* eslint-disable */
3+
{{>licenseInfo}}
4+
{{#apiInfo}}
5+
{{#apis}}
6+
{{#operations}}
7+
export * from './{{tsApiPackage}}/{{classFilename}}';
8+
{{/operations}}
9+
{{/apis}}
10+
{{/apiInfo}}
11+

0 commit comments

Comments
 (0)