const axios = require("axios");
import Fragments from "./queries/fragments/fragments.json";
class GraphQLClient {
/** The GraphQLClient retrieves data from the FAIRSharing API and sends it to the front-end.
* Be careful, this is a singleton and trying to cast new instances will return the existing instance. Be
* also careful, its constructor is async !!
* @returns {Promise} - to use this object you need to do "await new ClassName()" or use .then(callback)
*/
constructor() {
this.initalizeHeader();
if (GraphQLClient._instance) {
return GraphQLClient._instance;
}
GraphQLClient._instance = this;
this.url = process.env.VUE_APP_API_ENDPOINT + "/graphql";
}
/**
* Execute the given query (coming from a json file, see /queries/getRecords.json)
* @param {Object} query - the query coming from the JSON file
* sending to the API.
* @returns {Promise}
*/
async executeQuery(query) {
let client = this;
let queryString = {
query: `{${client.buildQuery(query)}}`,
};
let resp = await this.getData(queryString);
if (resp.data.errors) {
return resp.data.errors;
}
return resp.data.data;
}
/**
* Takes the query, post it with axios and returns the raw data
* @param {Object} queryString - processed request coming out of buildQuery() or a GraphQL query string
* @returns {Promise} - an axios promise representing the server response.
*/
async getData(queryString) {
let client = this;
const fullQuery = {
method: "post",
baseURL: client.url,
data: queryString,
headers: client.headers,
};
return axios(fullQuery);
}
/**
* Transform the JSON query into a string for graphQL
* @param {Object} query - the query coming from the JSON file
* @returns {Object} {query: queryString} - a valid graphQL query string to execute
*/
buildQuery(query) {
let client = this;
let queryString = `${query["queryName"]}`; // query name
// Handle query parameters
if (query.queryParam) {
queryString += "(";
Object.keys(query.queryParam).forEach(function (key) {
if (
typeof query.queryParam[key] === "boolean" ||
typeof query.queryParam[key] === "number"
) {
queryString += `${key}:${query.queryParam[key]} `;
} else if (typeof query.queryParam[key] === "string") {
//Modified to adjust multiple arguments in GraphQl query params
const regExp = /\(|\)|\{|\}/g;
const hasBrackets = regExp.test(query.queryParam[key]);
if (hasBrackets) queryString += `${key}:${query.queryParam[key]}`;
else queryString += `${key}:"${query.queryParam[key]}" `;
// queryString += `${key}:"${query.queryParam[key]}" `;
} else {
let param = [];
query.queryParam[key].forEach(function (paramVal) {
typeof paramVal !== "number"
? param.push('"' + paramVal + '"')
: param.push(paramVal);
});
queryString += `${key}:[${param.join(",")}]`;
}
});
queryString += ")";
}
// Handle query fields
if (query.fields) {
queryString += "{";
query.fields.forEach(function (field) {
if (typeof field === "string") {
queryString += ` ${field}`;
}
if (typeof field === "object") {
if ("$ref" in field) {
let myRef = Fragments[field["$ref"]];
for (let subField of myRef) {
if (typeof subField === "string") {
queryString += ` ${subField}`;
} else {
queryString += ` ${client.buildQuery(subField)}`;
}
}
} else {
queryString += ` ${field.name}{`;
field.fields.forEach(function (subField) {
if (typeof subField === "string") {
queryString += `${subField} `;
} else {
queryString += `${client.buildQuery(subField)}`;
}
});
queryString += "}";
}
}
});
queryString += "}";
}
return queryString;
}
/**
* Add the authorization token to the headers
* @param {String} jwt - the user json web token
*/
setHeader(jwt) {
this.headers["Authorization"] = `Bearer ${jwt}`;
}
initalizeHeader() {
this.headers = {
Accept: "application/json",
"Content-Type": "application/json",
};
this.headers["X-Client-Id"] = process.env.VUE_APP_CLIENT_ID;
/* istanbul ignore if */
if (this.headers["X-Client-Id"] === undefined) {
delete this.headers["X-Client-Id"];
}
}
}
export default GraphQLClient;