Skip to content

Fixes to javascript-apollo generator for proper module exports, type annotations #5892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ public JavascriptApolloClientCodegen() {

outputFolder = "generated-code/js";
modelTemplateFiles.put("model.mustache", ".js");
modelTestTemplateFiles.put("model_test.mustache", ".js");
// modelTestTemplateFiles.put("model_test.mustache", ".js");
apiTemplateFiles.put("api.mustache", ".js");
apiTestTemplateFiles.put("api_test.mustache", ".js");
// apiTestTemplateFiles.put("api_test.mustache", ".js");
// subfolder Javascript/es6
embeddedTemplateDir = templateDir = "Javascript-Apollo";
apiPackage = "api";
Expand Down Expand Up @@ -873,9 +873,9 @@ private String trimBrackets(String s) {
private String getJSDocType(CodegenModel cm, CodegenProperty cp) {
if (Boolean.TRUE.equals(cp.isContainer)) {
if (cp.containerType.equals("array"))
return "Array.<" + cp.items + ">";
return "Array.<" + getJSDocType(cm, cp.items) + ">";
else if (cp.containerType.equals("map"))
return "Object.<String, " + cp.items + ">";
return "Object.<String, " + getJSDocType(cm, cp.items) + ">";
}
String dataType = trimBrackets(cp.datatypeWithEnum);
if (cp.isEnum) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{>licenseInfo}}

import RESTDataSource from 'apollo-datasource-rest';
const { RESTDataSource } = require('apollo-datasource-rest');

{{#emitJSDoc}}/**
* @module {{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}ApiClient
Expand All @@ -13,34 +13,8 @@ import RESTDataSource from 'apollo-datasource-rest';
* @alias module:{{#invokerPackage}}{{invokerPackage}}/{{/invokerPackage}}ApiClient
* @class
*/{{/emitJSDoc}}
export default class ApiClient extends RESTDataSource {
constructor() {
super()

{{#emitJSDoc}}/**
* The authentication methods to be included for all API calls.
* @type {Array.<String>}
*/{{/emitJSDoc}}{{=< >=}}
this.authentications = {
<#authMethods>
<#isBasic>
<#isBasicBasic>
'<name>': {type: 'basic'}<^-last>,</-last>
</isBasicBasic>
<#isBasicBearer>
'<name>': {type: 'bearer'}<^-last>,</-last><#bearerFormat> // <&.></bearerFormat>
</isBasicBearer>
</isBasic>
<#isApiKey>
'<name>': {type: 'apiKey', 'in': <#isKeyInHeader>'header'</isKeyInHeader><^isKeyInHeader>'query'</isKeyInHeader>, name: '<keyParamName>'}<^-last>,</-last>
</isApiKey>
<#isOAuth>
'<name>': {type: 'oauth2'}<^-last>,</-last>
</isOAuth>
</authMethods>
}
}

class ApiClient extends RESTDataSource {
/** @private */
paramToString(param) {
if (param == undefined || param == null) {
return '';
Expand All @@ -52,8 +26,9 @@ export default class ApiClient extends RESTDataSource {
return param.toString();
}

parametrizePath(path, pathParams) {
return url.replace(/\{([\w-]+)\}/g, (fullMatch, key) => {
/** @private */
parameterizePath(path, pathParams) {
return path.replace(/\{([\w-]+)\}/g, (fullMatch, key) => {
var value;
if (pathParams.hasOwnProperty(key)) {
value = this.paramToString(pathParams[key]);
Expand All @@ -65,6 +40,7 @@ export default class ApiClient extends RESTDataSource {
});
}

/** @private */
isFileParam(param) {
// fs.ReadStream in Node.js and Electron (but not in runtime like browserify)
if (typeof require === 'function') {
Expand Down Expand Up @@ -95,6 +71,7 @@ export default class ApiClient extends RESTDataSource {
return false;
}

/** @private */
normalizeParams(params) {
var newParams = {};
for (var key in params) {
Expand All @@ -111,6 +88,7 @@ export default class ApiClient extends RESTDataSource {
return newParams;
}

/** @private */
buildCollectionParam(param, collectionFormat) {
if (param == null) {
return null;
Expand All @@ -132,86 +110,48 @@ export default class ApiClient extends RESTDataSource {
}
}

applyAuthOptions(fetchOptions, authNames) {
fetchOptions.headers = fetchOptions.headers || {};

authNames.forEach((authName) => {
var auth = this.authentications[authName];
switch (auth.type) {
case 'basic':
if (auth.username || auth.password) {
fetchOptions.headers['Authorization'] = 'Basic ' + base64.encode(auth.username + ":" + auth.password);
}

break;
case 'bearer':
case 'oauth2':
if (auth.accessToken) {
fetchOptions.headers['Authorization'] = 'Bearer ' + auth.accessToken;
}

break;
case 'apiKey':
if (auth.apiKey) {
var data = {};
if (auth.apiKeyPrefix) {
data[auth.name] = auth.apiKeyPrefix + ' ' + auth.apiKey;
} else {
data[auth.name] = auth.apiKey;
}

if (auth['in'] === 'header') {
Object.assign(fetchOptions.headers, data);
} else {
Object.assign(fetchOptions.params, data);
}
}

break;
default:
throw new Error('Unknown authentication type: ' + auth.type);
}
});
}

async callApi(path, httpMethod, pathParams,
queryParams, headerParams, formParams, bodyParam, authNames,
returnType) {

var parameterizedPath = this.parametrizePath(path, pathParams);
var fetchOptions = {
headers: headerParams,
params: queryParams
};

this.applyAuthOptions(fetchOptions, authNames);

var body = null;

if (bodyParam !== null && bodyParam !== undefined) {
body = bodyParam;
} else if (formParams !== null && formParams !== undefined) {
var _formParams = this.normalizeParams(formParams);
for (var key in _formParams) {
if (_formParams.hasOwnProperty(key)) {
body[key] = _formParams[key];
}
}
}
/** @private */
async callApi(path, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, fetchOptions, returnType) {
const finalFetchOptions = Object.assign({}, fetchOptions, {
headers: Object.assign({}, headerParams, fetchOptions.headers || {}),
})

var response;
var httpMethodFn = httpMethod.toLowerCase();
var parameterizedPath = this.parameterizePath(path, pathParams);

if (httpMethodFn == 'get' || httpMethodFn == 'delete') {
response = await this[httpMethodFn](parameterizedPath, fetchOptions);
response = await this[httpMethodFn](parameterizedPath, queryParams, finalFetchOptions);
} else {
response = await this[httpMethodFn](parameterizedPath, body, fetchOptions)
let body = null;

if (bodyParam !== null && bodyParam !== undefined) {
body = bodyParam;
} else if (formParams !== null && formParams !== undefined) {
var _formParams = this.normalizeParams(formParams);
for (var key in _formParams) {
if (_formParams.hasOwnProperty(key)) {
body[key] = _formParams[key];
}
}
}
response = await this[httpMethodFn](parameterizedPath, body, finalFetchOptions)
}

var convertedResponse = ApiClient.convertToType(response, returnType);
return convertedResponse;
}

/** @private */
compactObject(obj) {
const cleanObj = Object.keys(obj).reduce((acc, key) => {
const _acc = acc;
if (obj[key] !== undefined) _acc[key] = obj[key];
return _acc;
}, {})
return cleanObj;
}

static parseDate(str) {
return new Date(str);
}
Expand Down Expand Up @@ -297,3 +237,5 @@ ApiClient.CollectionFormatEnum = {
PIPES: '|',
MULTI: 'multi'
};

module.exports = ApiClient
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,16 @@

{{=< >=}}

import ApiClient from "../ApiClient";
<#imports>import <&import> from '../<#modelPackage><&modelPackage>/</modelPackage><import>';
const ApiClient = require("../ApiClient");
<#imports>const <&import> = require('../<#modelPackage><&modelPackage>/</modelPackage><import>');
</imports>

<#emitJSDoc>/**
* <baseName> service.
* @module <#invokerPackage><&invokerPackage>/</invokerPackage><#apiPackage><&apiPackage>/</apiPackage><classname>
* @version <&projectVersion>
*/</emitJSDoc>
export default class <&classname> extends ApiClient {

<#emitJSDoc>/**
* Constructs a new <&classname>. <#description>
* <description></description>
* @alias module:<#invokerPackage><&invokerPackage>/</invokerPackage><#apiPackage><&apiPackage>/</apiPackage><classname>
* @class
*/</emitJSDoc>
constructor() {
super();
this.baseURL = <#servers.0>basePath</servers.0><^servers.0>null</servers.0>;
}
class <&classname> extends ApiClient {

<#operations><#operation><#emitJSDoc>
/**<#summary>
Expand All @@ -31,9 +20,10 @@ export default class <&classname> extends ApiClient {
* @param {<&vendorExtensions.x-jsdoc-type>} <&paramName> <&description></required></allParams><#hasOptionalParams>
* @param {Object} opts Optional parameters<#allParams><^required>
* @param {<&vendorExtensions.x-jsdoc-type>} opts.<&paramName> <&description><#defaultValue> (default to <&.>)</defaultValue></required></allParams></hasOptionalParams>
* @param {RequestInit} fetchOptions Options passed to fetch()
<=| |=>* @return {Promise|#returnType|<|&vendorExtensions.x-jsdoc-type|>|/returnType|}|=< >=|
*/
</emitJSDoc> async <operationId>(<vendorExtensions.x-codegen-arg-list>) {
</emitJSDoc> async <operationId>(<vendorExtensions.x-codegen-arg-list>, fetchOptions) {
<#vendorExtensions.x-codegen-has-optional-params>
opts = opts || {};
</vendorExtensions.x-codegen-has-optional-params>
Expand All @@ -50,39 +40,31 @@ export default class <&classname> extends ApiClient {
let pathParams = {<#pathParams>
'<baseName>': <#required><paramName></required><^required>opts['<paramName>']</required><#hasMore>,</hasMore></pathParams>
};
let queryParams = {<#queryParams>
let queryParams = this.compactObject({<#queryParams>
'<baseName>': <#collectionFormat>this.buildCollectionParam(<#required><paramName></required><^required>opts['<paramName>']</required>, '<collectionFormat>')</collectionFormat><^collectionFormat><#required><paramName></required><^required>opts['<paramName>']</required></collectionFormat><#hasMore>,</hasMore></queryParams>
};
});
let headerParams = {<#headerParams>
'<baseName>': <#required><paramName></required><^required>opts['<paramName>']</required><#hasMore>,</hasMore></headerParams>
};
let formParams = {<#formParams>
let formParams = this.compactObject({<#formParams>
'<baseName>': <#collectionFormat>this.buildCollectionParam(<#required><paramName></required><^required>opts['<paramName>']</required>, '<collectionFormat>')</collectionFormat><^collectionFormat><#required><paramName></required><^required>opts['<paramName>']</required></collectionFormat><#hasMore>,</hasMore></formParams>
};
});

let authNames = [<#authMethods>'<name>'<#hasMore>, </hasMore></authMethods>];
let contentTypes = [<#consumes>'<& mediaType>'<#hasMore>, </hasMore></consumes>];
let accepts = [<#produces>'<& mediaType>'<#hasMore>, </hasMore></produces>];
let returnType = <#vendorExtensions.x-return-type><&vendorExtensions.x-return-type></vendorExtensions.x-return-type><^vendorExtensions.x-return-type>null</vendorExtensions.x-return-type>;
<#servers.0>
let basePaths = [<#servers>'<url>'<^-last>, </-last></servers>];
let basePath = basePaths[0]; // by default use the first one in "servers" defined in OpenAPI
if (typeof opts['_base_path_index'] !== 'undefined') {
if (opts['_base_path_index'] >= basePaths.length || opts['_base_path_index'] < 0) {
throw new Error("Invalid index " + opts['_base_path_index'] + " when selecting the host settings. Must be less than " + basePaths.length);
}
basePath = basePaths[opts['_base_path_index']];
}

</servers.0>

return this.callApi(
'<&path>', '<httpMethod>',
pathParams, queryParams, headerParams, formParams, postBody,
authNames, contentTypes, accepts, returnType
fetchOptions, returnType
);
}
</operation></operations>

}

module.exports = <&classname>
<={{ }}=>

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @enum {{=<% %>=}}{<%datatype%>}<%={{ }}=%>
* @readonly
*/{{/emitJSDoc}}
export default {{datatypeWithEnum}} = {
module.exports = {{datatypeWithEnum}} = {
{{#allowableValues}}{{#enumVars}}
{{#emitJSDoc}}/**
* value: {{{value}}}
Expand Down
Loading