Revert "Support language N4JS (#15089)" (#15396)

This reverts commit a83470066e.
This commit is contained in:
William Cheng
2023-05-03 15:43:07 +08:00
committed by GitHub
parent a83470066e
commit aea7cef6a1
28 changed files with 1 additions and 4086 deletions

View File

@@ -1,671 +0,0 @@
package org.openapitools.codegen.languages;
import static org.openapitools.codegen.CodegenConstants.API_NAME_PREFIX;
import static org.openapitools.codegen.CodegenConstants.API_NAME_PREFIX_DESC;
import static org.openapitools.codegen.CodegenConstants.API_PACKAGE;
import static org.openapitools.codegen.CodegenConstants.API_PACKAGE_DESC;
import static org.openapitools.codegen.CodegenConstants.MODEL_PACKAGE;
import static org.openapitools.codegen.CodegenConstants.MODEL_PACKAGE_DESC;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.CodegenSecurity;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.IJsonSchemaValidationProperties;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationMap;
import org.openapitools.codegen.model.OperationsMap;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.ComposedSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
public class N4jsClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String CHECK_REQUIRED_PARAMS_NOT_NULL = "checkRequiredParamsNotNull";
public static final String CHECK_SUPERFLUOUS_BODY_PROPS = "checkSuperfluousBodyProps";
public static final String GENERATE_DEFAULT_API_EXECUTER = "generateDefaultApiExecuter";
final Logger LOGGER = LoggerFactory.getLogger(N4jsClientCodegen.class);
final Set<String> forbiddenChars = new HashSet<>();
private boolean checkRequiredBodyPropsNotNull = true;
private boolean checkSuperfluousBodyProps = true;
private boolean generateDefaultApiExecuter = true;
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "n4js";
}
public String getHelp() {
return "Generates a n4js client.";
}
public N4jsClientCodegen() {
super();
// disable since otherwise Modules/Class are not generated iff used as
// parameters only
GlobalSettings.setProperty("skipFormModel", "false");
specialCharReplacements.clear();
outputFolder = "generated-code" + File.separator + "n4js";
modelTemplateFiles.put("model.mustache", ".n4jsd");
apiTemplateFiles.put("api.mustache", ".n4js");
embeddedTemplateDir = templateDir = "n4js";
apiPackage = "";
modelPackage = "";
typeMapping = new HashMap<String, String>();
typeMapping.put("Set", "Set");
typeMapping.put("set", "Set");
typeMapping.put("Array", "Array");
typeMapping.put("array", "Array");
typeMapping.put("boolean", "boolean");
typeMapping.put("string", "string");
typeMapping.put("char", "string");
typeMapping.put("float", "number");
typeMapping.put("long", "int");
typeMapping.put("short", "int");
typeMapping.put("int", "int");
typeMapping.put("integer", "int");
typeMapping.put("number", "number");
typeMapping.put("double", "number");
typeMapping.put("object", "object");
typeMapping.put("Map", "any");
typeMapping.put("map", "any");
typeMapping.put("date", "string");
typeMapping.put("DateTime", "string");
typeMapping.put("binary", "any");
typeMapping.put("File", "any");
typeMapping.put("file", "any");
typeMapping.put("ByteArray", "string");
typeMapping.put("UUID", "string");
typeMapping.put("URI", "string");
typeMapping.put("Error", "Error");
typeMapping.put("AnyType", "any");
importMapping.clear(); // not used
supportsInheritance = true;
supportsMultipleInheritance = false;
reservedWords.addAll(Arrays.asList(
// local variable names used in API methods (endpoints)
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
"requestOptions",
// N4JS reserved words
"abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue",
"debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final",
"finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int",
"interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public",
"return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true",
"try", "typeof", "var", "void", "volatile", "while", "with", "yield"));
languageSpecificPrimitives = new HashSet<>(Arrays.asList("string", "String", "boolean", "number", "int",
"Object", "object", "Array", "any", "any+", "Error"));
defaultIncludes.add("~Object+");
defaultIncludes.add("Object+");
forbiddenChars.add("@");
cliOptions.clear();
cliOptions.add(new CliOption(API_PACKAGE, API_PACKAGE_DESC));
cliOptions.add(new CliOption(MODEL_PACKAGE, MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(API_NAME_PREFIX, API_NAME_PREFIX_DESC));
cliOptions.add(new CliOption(CHECK_REQUIRED_PARAMS_NOT_NULL,
"Iff true null-checks are performed for required parameters."));
cliOptions.add(new CliOption(CHECK_SUPERFLUOUS_BODY_PROPS,
"Iff true a new copy of the given body object is transmitted. This copy only contains those properties defined in its model specification."));
cliOptions.add(new CliOption(GENERATE_DEFAULT_API_EXECUTER,
"Iff true a default implementation of the api executer interface is generated."));
}
@Override
public void processOpts() {
super.processOpts();
supportingFiles.clear();
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("ApiHelper.mustache", apiPackage, "ApiHelper.n4js"));
checkRequiredBodyPropsNotNull = processBooleanOpt(CHECK_REQUIRED_PARAMS_NOT_NULL, checkRequiredBodyPropsNotNull);
checkSuperfluousBodyProps = processBooleanOpt(CHECK_SUPERFLUOUS_BODY_PROPS, checkSuperfluousBodyProps);
generateDefaultApiExecuter = processBooleanOpt(GENERATE_DEFAULT_API_EXECUTER, generateDefaultApiExecuter);
if (additionalProperties.get(API_PACKAGE) instanceof String) {
apiPackage = additionalProperties.get(API_PACKAGE).toString();
} else {
additionalProperties.put(API_PACKAGE, apiPackage);
}
if (additionalProperties.get(MODEL_PACKAGE) instanceof String) {
modelPackage = additionalProperties.get(MODEL_PACKAGE).toString();
} else {
additionalProperties.put(MODEL_PACKAGE, modelPackage);
}
if (additionalProperties.get(API_NAME_PREFIX) instanceof String) {
apiNamePrefix = additionalProperties.get(API_NAME_PREFIX).toString();
} else {
additionalProperties.put(API_NAME_PREFIX, apiNamePrefix);
}
}
private boolean processBooleanOpt(String OPT, boolean defaultValue) {
boolean passedValue = defaultValue;
if (additionalProperties.containsKey(OPT)) {
Object value = additionalProperties.get(OPT);
if (value instanceof Boolean) {
passedValue = (Boolean) value;
} else {
try {
passedValue = Boolean.parseBoolean(value.toString());
} catch (Exception e) {
// ignore
}
}
}
additionalProperties.put(OPT, passedValue);
return defaultValue;
}
@Override
public String toModelFilename(String name) {
String modelFilename = super.toModelFilename(name);
if (typeMapping.containsKey(modelFilename) || defaultIncludes.contains(modelFilename)) {
return modelFilename;
}
return modelFilename;
}
public boolean checkRequiredBodyPropsNotNull() {
return checkRequiredBodyPropsNotNull;
}
public boolean checkSuperfluousBodyProps() {
return checkSuperfluousBodyProps;
}
public boolean generateDefaultApiExecuter() {
return generateDefaultApiExecuter;
}
@Override
public boolean getUseInlineModelResolver() {
return false;
}
@Override
public void setOpenAPI(OpenAPI openAPI) {
super.setOpenAPI(openAPI);
typeAliases.put("object", "~Object+");
}
@Override
protected boolean isReservedWord(String word) {
// case sensitive matching
return reservedWords.contains(word);
}
@Override
public String toAnyOfName(List<String> names, ComposedSchema composedSchema) {
List<String> types = getTypesFromSchemas(composedSchema.getAnyOf());
return String.join(" | ", types);
}
@Override
public String toOneOfName(List<String> names, ComposedSchema composedSchema) {
List<String> types = getTypesFromSchemas(composedSchema.getOneOf());
return String.join(" | ", types);
}
@Override
public String toAllOfName(List<String> names, ComposedSchema composedSchema) {
List<String> types = getTypesFromSchemas(composedSchema.getAllOf());
return String.join(" & ", types);
}
/**
* Extracts the list of type names from a list of schemas. Excludes `AnyType` if
* there are other valid types extracted.
*
* @param schemas list of schemas
* @return list of types
*/
@SuppressWarnings("rawtypes")
protected List<String> getTypesFromSchemas(List<Schema> schemas) {
List<Schema> filteredSchemas = schemas.size() > 1 ? schemas.stream()
.filter(schema -> !"AnyType".equals(super.getSchemaType(schema))).collect(Collectors.toList())
: schemas;
return filteredSchemas.stream().map(schema -> getTypeDeclaration(schema)).distinct()
.collect(Collectors.toList());
}
@Override
protected void addImports(Set<String> importsToBeAddedTo, IJsonSchemaValidationProperties type) {
Set<String> imports = type.getImports(importContainerType, importBaseType, generatorMetadata.getFeatureSet());
Set<String> mappedImports = new HashSet<>();
for (String imp : imports) {
String mappedImp = imp;
if (typeMapping.containsKey(imp)) {
mappedImp = typeMapping.get(imp);
} else {
mappedImp = imp;
}
mappedImports.add(mappedImp);
}
addImports(importsToBeAddedTo, mappedImports);
}
@Override
protected void addImport(Set<String> importsToBeAddedTo, String type) {
String[] parts = splitComposedType(type);
for (String s : parts) {
super.addImport(importsToBeAddedTo, s);
}
}
private String[] splitComposedType(String name) {
return name.replace(" ", "").split("[|&<>]");
}
@Override
public ModelsMap postProcessModels(ModelsMap objs) {
objs = super.postProcessModels(objs);
for (ModelMap modelMap : objs.getModels()) {
CodegenModel cgModel = modelMap.getModel();
if (cgModel.unescapedDescription != null && !cgModel.unescapedDescription.contains("\n * ")) {
cgModel.description = escapeTextWhileAllowingNewLines(cgModel.unescapedDescription.trim()).replace("\n",
"\n * ");
}
}
postProcessModelsEnum(objs); // enable enums
return objs;
}
@Override
protected void addImportsForPropertyType(CodegenModel model, CodegenProperty property) {
if (model.getIsAnyType()) {
return; // disable (unused) imports created for properties of type aliases
}
super.addImportsForPropertyType(model, property);
}
@Override
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
objs = super.postProcessAllModels(objs);
for (String modelName : objs.keySet()) {
ModelsMap modelsMap = objs.get(modelName);
// imports
List<Map<String, String>> imports = modelsMap.getImports();
ArrayList<Map<String, String>> n4jsImports = new ArrayList<Map<String, String>>();
modelsMap.put("n4jsimports", n4jsImports);
String className = modelsMap.get("classname").toString();
for (Map<String, String> imp : imports) {
Map<String, String> n4jsImport = toN4jsImports(className, objs, imp);
if (n4jsImport != null) {
n4jsImports.add(n4jsImport);
}
}
// app description -> module documentation
adjustDescriptionWithNewLines(modelsMap);
}
return objs;
}
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap operations, List<ModelMap> allModels) {
OperationMap objs = operations.getOperations();
boolean needImportCleanCopyBody = false;
// The api.mustache template requires all of the auth methods for the whole api
// Loop over all the operations and pick out each unique auth method
Map<String, CodegenSecurity> authMethodsMap = new HashMap<>();
for (CodegenOperation op : objs.getOperation()) {
if (op.hasAuthMethods) {
for (CodegenSecurity sec : op.authMethods) {
authMethodsMap.put(sec.name, sec);
}
}
if (op.bodyParam != null && !op.bodyParam.vars.isEmpty()) {
needImportCleanCopyBody = true;
}
if (op.responses != null && op.responses.size() > 0) {
Map<String, CodegenResponse> responses2xx = new LinkedHashMap<>();
Map<String, CodegenResponse> responses4xx = new LinkedHashMap<>();
for (CodegenResponse response : op.responses) {
if (response.is2xx) {
responses2xx.put(response.baseType, response);
}
if (response.is4xx) {
responses4xx.put(response.baseType, response);
}
}
op.vendorExtensions.put("responses2xx", new ArrayList<>(responses2xx.values()));
op.vendorExtensions.put("responses4xx", new ArrayList<>(responses4xx.values()));
}
}
operations.put("needImportCleanCopyBody", needImportCleanCopyBody);
// If there were any auth methods specified add them to the operations context
if (!authMethodsMap.isEmpty()) {
operations.put("authMethods", authMethodsMap.values());
operations.put("hasAuthMethods", true);
}
// Add additional filename information for model imports in the apis
Iterator<Map<String, String>> iter = operations.getImports().iterator();
while (iter.hasNext()) {
Map<String, String> im = iter.next();
String className = im.get("classname");
className = convertToModelName(className);
String adjClassName = typeMapping.getOrDefault(className, className);
if (needToImport(adjClassName)) {
im.put("classname", className);
im.put("filename", toModelImport(className));
} else {
iter.remove();
}
}
// app description -> module documentation
adjustDescriptionWithNewLines(additionalProperties);
return operations;
}
private String convertToModelName(String modelName) {
if (modelName == null) {
return modelName;
}
Schema<?> schema = ModelUtils.getSchema(openAPI, modelName);
if (schema == null) {
return modelName;
}
if (ModelUtils.isObjectSchema(schema)) {
return toModelFilename(modelName);
}
return modelName;
}
private void adjustDescriptionWithNewLines(Map<String, Object> map) {
if (map.containsKey("appDescriptionWithNewLines")
&& !map.get("appDescriptionWithNewLines").toString().contains("\n * ")) {
String appDescriptionWithNewLines = map.get("appDescriptionWithNewLines").toString();
appDescriptionWithNewLines = appDescriptionWithNewLines.trim().replace("\n", "\n * ");
map.put("appDescriptionWithNewLines", appDescriptionWithNewLines);
}
}
private Map<String, String> toN4jsImports(String className, Map<String, ModelsMap> objs, Map<String, String> imp) {
String modelImpName = imp.get("import");
if (modelImpName == null) {
return null;
}
String modelName = fromModelImport(modelImpName);
if (!objs.containsKey(modelName)) {
return null;
}
ModelsMap modelsMap = objs.get(modelName);
String impClassName = modelsMap.get("classname").toString();
if (impClassName == null || Objects.equals(impClassName, className)) {
return null;
}
Map<String, String> n4jsImport = new HashMap<>();
n4jsImport.put("elementname", impClassName);
n4jsImport.put("modulename", modelImpName);
return n4jsImport;
}
@Override
public String toModelImport(String name) {
if ("".equals(modelPackage())) {
return name;
} else {
return modelPackage() + "/" + name;
}
}
protected String fromModelImport(String modelImportName) {
if ("".equals(modelPackage())) {
return modelImportName;
} else if (modelImportName == null) {
return modelImportName;
} else {
if (modelImportName.startsWith(modelPackage() + "/")) {
String nameWithoutModelPackage = modelImportName.substring(1 + modelPackage().length());
if (modelNamePrefix != null && nameWithoutModelPackage.startsWith(modelNamePrefix)) {
return nameWithoutModelPackage.substring(modelNamePrefix.length());
}
return nameWithoutModelPackage;
}
return modelImportName;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
Schema<?> items = getSchemaItems((ArraySchema) p);
return getTypeDeclaration(unaliasSchema(items)) + "[]";
} else if (ModelUtils.isMapSchema(p)) {
// Schema<?> inner = getSchemaAdditionalProperties(p);
// return "~Object with { [key: string]: " + getTypeDeclaration(unaliasSchema(inner)) + "; }";
return "~Object+";
} else if (ModelUtils.isStringSchema(p)) {
if (p.getEnum() != null) {
return enumValuesToEnumTypeUnion(p.getEnum(), "string");
}
} else if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p)) {
// Handle integer and double enums
if (p.getEnum() != null) {
return numericEnumValuesToEnumTypeUnion(new ArrayList<Number>(p.getEnum()));
}
} else if (ModelUtils.isFileSchema(p)) {
return "File";
} else if (ModelUtils.isObjectSchema(p)
|| ModelUtils.isObjectSchema(ModelUtils.getReferencedSchema(openAPI, p))) {
String result = super.getTypeDeclaration(p);
return toModelFilename(result);
} else if (ModelUtils.isBinarySchema(p)) {
return "ArrayBuffer";
}
return super.getTypeDeclaration(p);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
protected String getParameterDataType(Parameter parameter, Schema p) {
// handle enums of various data types
if (ModelUtils.isArraySchema(p)) {
ArraySchema mp1 = (ArraySchema) p;
Schema<?> inner = mp1.getItems();
return getParameterDataType(parameter, inner) + "[]";
} else if (ModelUtils.isMapSchema(p)) {
// Schema<?> inner = getAdditionalProperties(p);
// return "~Object with { [key: string]: " + this.getParameterDataType(parameter, inner) + "; }";
return "~Object+";
} else if (ModelUtils.isStringSchema(p)) {
// Handle string enums
if (p.getEnum() != null) {
return enumValuesToEnumTypeUnion(p.getEnum(), "string");
}
} else if (ModelUtils.isObjectSchema(p)
|| ModelUtils.isObjectSchema(ModelUtils.getReferencedSchema(openAPI, p))) {
String result = super.getTypeDeclaration(p);
return toModelFilename(result);
} else if (ModelUtils.isIntegerSchema(p) || ModelUtils.isNumberSchema(p)) {
// Handle integer and double enums
if (p.getEnum() != null) {
return numericEnumValuesToEnumTypeUnion(new ArrayList<Number>(p.getEnum()));
}
}
return this.getTypeDeclaration(p);
}
@Override
protected String getSingleSchemaType(@SuppressWarnings("rawtypes") Schema schema) {
Schema<?> unaliasSchema = unaliasSchema(schema);
if (StringUtils.isNotBlank(unaliasSchema.get$ref())) {
String schemaName = ModelUtils.getSimpleRef(unaliasSchema.get$ref());
if (StringUtils.isNotEmpty(schemaName)) {
if (schemaMapping.containsKey(schemaName)) {
return schemaName;
}
}
}
return super.getSingleSchemaType(unaliasSchema);
}
/**
* Converts a list of strings to a literal union for representing enum values as
* a type. Example output: 'available' | 'pending' | 'sold'
*
* @param values list of allowed enum values
* @param dataType either "string" or "number"
* @return a literal union for representing enum values as a type
*/
private String enumValuesToEnumTypeUnion(List<String> values, String dataType) {
StringBuilder b = new StringBuilder();
boolean isFirst = true;
for (String value : values) {
if (!isFirst) {
b.append(" | ");
}
b.append(toEnumValue(value, dataType));
isFirst = false;
}
return b.toString();
}
/**
* Converts a list of numbers to a literal union for representing enum values as
* a type. Example output: 3 | 9 | 55
*
* @param values a list of numbers
* @return a literal union for representing enum values as a type
*/
private String numericEnumValuesToEnumTypeUnion(List<Number> values) {
List<String> stringValues = new ArrayList<>();
for (Number value : values) {
stringValues.add(value.toString());
}
return enumValuesToEnumTypeUnion(stringValues, "number");
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
if (property.unescapedDescription != null && property.unescapedDescription.contains("\n")) {
property.description = escapeTextWhileAllowingNewLines(property.unescapedDescription.trim()).replace("\n",
"\n * ");
}
}
@Override
public String escapeText(String input) {
input = escapeTextWhileAllowingNewLines(input);
if (input == null) {
return input;
}
// remove \n, \r
return input.replaceAll("[\\n\\r]", " ");
}
@Override
public String escapeTextWhileAllowingNewLines(String input) {
if (input == null) {
return input;
}
// remove \t
// outer unescape to retain the original multi-byte characters
// finally escalate characters avoiding code injection
return escapeUnsafeCharacters(
StringEscapeUtils.unescapeEcmaScript(StringEscapeUtils.escapeEcmaScript(input).replace("\\/", "/"))
.replaceAll("[\\t]", " "));
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String toVarName(final String name) {
String name2 = super.toVarName(name);
for (String forbiddenChar : forbiddenChars) {
if (name2.contains(forbiddenChar)) {
return "[\"" + name2 + "\"]";
}
}
return name2;
}
@Override
public String toParamName(String name) {
String name2 = super.toParamName(name);
for (String forbiddenChar : forbiddenChars) {
if (name2.contains(forbiddenChar)) {
return "[\"" + name2 + "\"]";
}
}
return name2;
}
@Override
public String escapeQuotationMark(String input) {
// remove ', " to avoid code injection
return input.replace("\"", "").replace("'", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
}

View File

@@ -81,7 +81,6 @@ org.openapitools.codegen.languages.K6ClientCodegen
org.openapitools.codegen.languages.LuaClientCodegen
org.openapitools.codegen.languages.MarkdownDocumentationCodegen
org.openapitools.codegen.languages.MysqlSchemaCodegen
org.openapitools.codegen.languages.N4jsClientCodegen
org.openapitools.codegen.languages.NimClientCodegen
org.openapitools.codegen.languages.NodeJSExpressServerCodegen
org.openapitools.codegen.languages.ObjcClientCodegen

View File

@@ -1,119 +0,0 @@
/**
* Implemented by client
*/
export public interface ~ApiExecuterI {
public <R, E> async exec(
method: string,
path: string,
pathParams: ~Object+,
queryParams: ~Object+,
headerParams: ~Object+,
payloadContentType: string,
body: any+) : Promise<R, Object|ApiError<E>>;
}
export public interface ~ApiError<T> {
public resultBody?: T;
}
{{#checkRequiredParamsNotNull}}
export public function checkRequiredParams(apiName: string, params: ~Object+) : void {
for (const key of Object.keys(params)) {
const arg = params[key];
if (arg == null) {
throw new Error('Required parameter ' + key + ' was null or undefined when calling ' + apiName + '.');
}
}
}
{{/checkRequiredParamsNotNull}}
{{#checkSuperfluousBodyProps}}
export public function <T> cleanCopyBody(t : T+, ...properties: string) : ~T {
const copy : ~T+ = {};
for (const prop in properties) {
copy[prop] = t.prop;
}
return copy;
}
{{/checkSuperfluousBodyProps}}
{{#generateDefaultApiExecuter}}
/**
* Default implementation of ApiExecuterI
*
* The following dependencies are necessary:
* - n4js-runtime-esnext
* - n4js-runtime-es2015
* - n4js-runtime-html5
*/
export public class FetchApiExec implements ApiExecuterI {
public apiOrigin: string;
const jsonTypes = ["application/json", "application/problem+json"];
@Override
public <R, E> async exec(
method: string,
path: string,
pathParams: ~Object+,
queryParams: ~Object+,
headerParams: ~Object+,
payloadContentType: string,
body: any+
): Promise<R, Object|ApiError<E>> {
if (pathParams) {
for (const [k, v] of Object.entries(pathParams)) {
path = path.replace(`{${k}}`, encodeURIComponent(String(v)));
}
}
const query: string[] = [];
if (queryParams) {
for (const [k, v] of Object.entries(queryParams)) {
query.push(`${k}=${encodeURIComponent(String(v))}`);
}
}
let url = `${this.apiOrigin}${path}`;
if (query.length) {
url += `?${query.join("&")}`;
}
const headers: Object+ = {};
if (payloadContentType) {
headers["content-type"] = payloadContentType;
if (this.constructor.jsonTypes.includes(payloadContentType)) {
body = JSON.stringify(body);
}
}
Object.assign(headers, headerParams);
return await this.<R,E>fetchExec(url, {
method,
headers,
body,
});
}
protected <R, E> async fetchExec(url: string, reqInit: RequestInit): Promise<R, Object|ApiError<E>> {
const resp = await fetch(url, reqInit);
if (resp.status !== 204) {
const contentType = (resp.headers.get("content-type") || "").split(";")[0];
const body = this.constructor.jsonTypes.includes(contentType)
? await resp.json()
: await resp.text();
if (!resp.ok) {
await this.handleError(resp, body);
}
return body as R;
}
return null;
}
protected <E> async handleError(resp: Response, body): Promise<undefined, ApiError<E>> {
throw {body: body};
}
}
{{/generateDefaultApiExecuter}}

View File

@@ -1,55 +0,0 @@
# Documentation for {{appName}}
- API version: {{appVersion}}
{{^hideGenerationTimestamp}}
- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}
{{{appDescriptionWithNewLines}}}
{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}
*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*
## Getting started
Configure the following elements:
- In open-api-n4js.yaml please add under 'additionalProperties':
- property 'fetchExecuterConstName'
- property 'fetchExecuterConstImplPath'
- The generated output directory needs to be augmented with an implementing n4js file
## Example
**open-api-n4js.yaml**
```yaml
generatorName: n4js
outputDir: /working_dir/gen-n4js/
inputSpec: /working_dir/api-spec/main.yaml
templateDir: /openapi-generator/modules/openapi-generator/src/main/resources/n4js
additionalProperties:
fetchExecuterConstName: "FETCH_EXEC"
fetchExecuterConstImplPath: "FetchExecuterImpl"
```
**FetchExecuterImpl.n4js**
```typescript
import {FetchExecuterI} from "api/ApiHelper";
export public const FETCH_EXEC = new FetchExecuterMock();
export public class FetchExecuterMock implements FetchExecuterI {
@Override
public async run(
path: string,
query: ~Object=,
reqInit: ~Object= {}): ~Object with {get status() : number, json(): Promise<any>} {
return null;
}
}
```

View File

@@ -1,53 +0,0 @@
{{>licenseInfo}}
import { ApiExecuterI, ApiError{{#checkRequiredParamsNotNull}}, checkRequiredParams{{/checkRequiredParamsNotNull}}{{#checkSuperfluousBodyProps}}{{#needImportCleanCopyBody}}, cleanCopyBody{{/needImportCleanCopyBody}}{{/checkSuperfluousBodyProps}} } from "{{{apiPackage}}}/ApiHelper"
{{#imports}}
import { {{classname}} } from '{{filename}}';
{{/imports}}
{{#operations}}
{{#description}}
/*
* {{&description}}
*/
{{/description}}
{{#operation}}
/**
{{#notes}}
* {{&notes}}
{{/notes}}
{{#summary}}
* @summary {{&summary}}
{{/summary}}
* @param fe Callback interface that runs the fetch query
{{#allParams}}
* @param {{paramName}} {{description}}
{{/allParams}}
{{#responses}}
* @response {{code}} [{{#dataType}}{{.}}{{/dataType}}{{^dataType}}undefined{{/dataType}}] {{message}}
{{/responses}}
*/
export public async function {{{classname}}}__{{{nickname}}}(fe : ApiExecuterI, {{#allParams}}{{{paramName}}}: {{{dataType}}}{{^required}}={{/required}}{{^-last}}, {{/-last}}{{/allParams}}) : Promise<{{#returnType}}{{.}}{{/returnType}}{{^returnType}}undefined{{/returnType}}, Object{{#vendorExtensions}}{{#responses4xx.0}} | ApiError<{{#responses4xx}}{{{baseType}}}{{^-last}} | {{/-last}}{{/responses4xx}}>{{/responses4xx.0}}{{/vendorExtensions}}> {
{{#checkRequiredParamsNotNull}} checkRequiredParams('{{{nickname}}}', { {{#allParams}}{{#required}}'{{{paramName}}}': {{{paramName}}}{{^-last}}, {{/-last}}{{/required}}{{/allParams}} });
{{/checkRequiredParamsNotNull}}
const _pathParams = { {{#pathParams}}
'{{baseName}}': {{{paramName}}}{{^-last}},{{/-last}} {{/pathParams}}};
const _queryParams = { {{#queryParams}}
'{{baseName}}': {{{paramName}}}{{^-last}},{{/-last}} {{/queryParams}}};
const _headerParams = { {{#headerParams}}
'{{baseName}}': {{{paramName}}}{{^-last}},{{/-last}} {{/headerParams}}};
const _body = {{^bodyParam}}undefined{{/bodyParam}}{{#bodyParam}}{{#vars.empty}}{{{paramName}}}{{/vars.empty}}{{^vars.empty}}{{#checkSuperfluousBodyProps}}cleanCopyBody({{{paramName}}}{{#vars}}, '{{{baseName}}}'{{/vars}}){{/checkSuperfluousBodyProps}}{{^checkSuperfluousBodyProps}}{{{paramName}}}{{/checkSuperfluousBodyProps}}{{/vars.empty}}{{/bodyParam}};
{{#returnType}}return {{/returnType}}await fe.{{#returnType}}<{{.}}, {{#vendorExtensions}}{{^responses4xx.0}}undefined{{/responses4xx.0}}{{#responses4xx.0}}{{#responses4xx}}{{{baseType}}}{{^-last}} | {{/-last}}{{/responses4xx}}{{/responses4xx.0}}{{/vendorExtensions}}>{{/returnType}}exec(
'{{httpMethod}}', '{{{basePathWithoutHost}}}' + '{{{path}}}',
_pathParams, _queryParams, _headerParams,
{{#responses2xx.0}}'{{{mediaType}}}'{{/responses2xx.0}}{{^responses2xx.0}}undefined{{/responses2xx.0}},
_body
);
}
{{/operation}}
{{/operations}}

View File

@@ -1,11 +0,0 @@
/*
* {{{appName}}}
* {{{appDescriptionWithNewLines}}}
*
* {{#version}}The version of the OpenAPI document: {{{.}}}{{/version}}
* {{#infoEmail}}Contact: {{{.}}}{{/infoEmail}}
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

View File

@@ -1,45 +0,0 @@
{{>licenseInfo}}
{{#models}}
{{#model}}
{{#n4jsimports}}
import { {{{elementname}}} } from '{{modulename}}';
{{/n4jsimports}}
{{#description}}
/**
* {{{.}}}
*/
{{/description}}
{{#isModel}}
export external public interface ~{{{classname}}} {{#parent}}extends {{{.}}} {{/parent}}{
{{#vars}}
{{#description}}
/**
* {{{.}}}
*/
{{/description}}
public {{{name}}}{{^required}}?{{/required}}: {{{dataType}}};
{{/vars}}
}
{{/isModel}}
{{#isAnyType}}
export external public type {{{classname}}} = {{{dataType}}};
{{/isAnyType}}
{{#isEnum}}
{{#isString}}
@StringBased
{{/isString}}
{{#isNumber}}
@NumberBased
{{/isNumber}}
export external public enum {{{classname}}} {
{{#allowableValues}}
{{#enumVars}}
{{{name}}}: {{{value}}}{{^-last}},{{/-last}}
{{/enumVars}}
{{/allowableValues}}
}
{{/isEnum}}
{{/model}}
{{/models}}

View File

@@ -1,46 +0,0 @@
package org.openapitools.codegen.n4js;
import static java.lang.Boolean.parseBoolean;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.openapitools.codegen.CodegenConstants.API_NAME_PREFIX;
import static org.openapitools.codegen.CodegenConstants.API_PACKAGE;
import static org.openapitools.codegen.CodegenConstants.MODEL_PACKAGE;
import static org.openapitools.codegen.languages.N4jsClientCodegen.CHECK_REQUIRED_PARAMS_NOT_NULL;
import static org.openapitools.codegen.languages.N4jsClientCodegen.CHECK_SUPERFLUOUS_BODY_PROPS;
import static org.openapitools.codegen.languages.N4jsClientCodegen.GENERATE_DEFAULT_API_EXECUTER;
import static org.openapitools.codegen.options.N4jsClientCodegenOptionsProvider.CHECK_REQUIRED_PARAMS_NOT_NULL__VALUE;
import static org.openapitools.codegen.options.N4jsClientCodegenOptionsProvider.CHECK_SUPERFLUOUS_BODY_PROPS__VALUE;
import static org.openapitools.codegen.options.N4jsClientCodegenOptionsProvider.GENERATE_DEFAULT_API_EXECUTER__VALUE;
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.N4jsClientCodegen;
import org.openapitools.codegen.options.N4jsClientCodegenOptionsProvider;
public class N4jsClientCodegenOptionsTest extends AbstractOptionsTest {
private N4jsClientCodegen codegen = mock(N4jsClientCodegen.class, mockSettings);
public N4jsClientCodegenOptionsTest() {
super(new N4jsClientCodegenOptionsProvider());
}
@Override
protected CodegenConfig getCodegenConfig() {
return codegen;
}
@Override
protected void verifyOptions() {
assertEquals(parseBoolean(CHECK_REQUIRED_PARAMS_NOT_NULL__VALUE),
codegen.additionalProperties().get(CHECK_REQUIRED_PARAMS_NOT_NULL));
assertEquals(parseBoolean(CHECK_SUPERFLUOUS_BODY_PROPS__VALUE),
codegen.additionalProperties().get(CHECK_SUPERFLUOUS_BODY_PROPS));
assertEquals(parseBoolean(GENERATE_DEFAULT_API_EXECUTER__VALUE),
codegen.additionalProperties().get(GENERATE_DEFAULT_API_EXECUTER));
assertEquals("", codegen.additionalProperties().get(API_PACKAGE));
assertEquals("", codegen.additionalProperties().get(MODEL_PACKAGE));
assertEquals("", codegen.additionalProperties().get(API_NAME_PREFIX));
}
}

View File

@@ -1,39 +0,0 @@
package org.openapitools.codegen.options;
import java.util.Map;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.languages.N4jsClientCodegen;
import com.google.common.collect.ImmutableMap;
public class N4jsClientCodegenOptionsProvider implements OptionsProvider {
public static final String PROJECT_NAME_VALUE = "OpenAPI";
public static final String CHECK_REQUIRED_PARAMS_NOT_NULL__VALUE = "true";
public static final String CHECK_SUPERFLUOUS_BODY_PROPS__VALUE = "true";
public static final String GENERATE_DEFAULT_API_EXECUTER__VALUE = "true";
@Override
public String getLanguage() {
return "n4js";
}
@Override
public Map<String, String> createOptions() {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
return builder
.put(N4jsClientCodegen.CHECK_REQUIRED_PARAMS_NOT_NULL, CHECK_REQUIRED_PARAMS_NOT_NULL__VALUE)
.put(N4jsClientCodegen.CHECK_SUPERFLUOUS_BODY_PROPS, CHECK_SUPERFLUOUS_BODY_PROPS__VALUE)
.put(N4jsClientCodegen.GENERATE_DEFAULT_API_EXECUTER, GENERATE_DEFAULT_API_EXECUTER__VALUE)
.put(CodegenConstants.API_PACKAGE, "")
.put(CodegenConstants.MODEL_PACKAGE, "")
.put(CodegenConstants.API_NAME_PREFIX, "")
.build();
}
@Override
public boolean isServer() {
return false;
}
}