topcoder-react-lib
Version:
The implementation of TC lib for ReactJS projects
148 lines (135 loc) • 4.25 kB
JavaScript
/**
* @module "services.submission"
* @desc This module provides a service for convenient manipulation with
* Topcoder submissions via TC API. Currently only used for MM challenges
*/
import _ from 'lodash';
import qs from 'qs';
import { setErrorIcon, ERROR_ICON_TYPES } from '../utils/errors';
import { getApi } from './api';
/**
* Helper method that checks for HTTP error response v5 and throws Error in this case.
* @param {Object} res HTTP response object
* @return {Object} API JSON response object
* @private
*/
async function checkErrorV5(res) {
if (!res.ok) {
if (res.status >= 500) {
setErrorIcon(ERROR_ICON_TYPES.API, '/challenges', res.statusText);
}
throw new Error(res.statusText);
}
const jsonRes = (await res.json());
if (jsonRes.message) {
throw new Error(res.message);
}
return {
result: jsonRes,
headers: res.headers,
};
}
/**
* Submission service.
*/
class SubmissionsService {
/**
* Creates a new SubmissionService instance.
* @param {String} tokenV3 Optional. Auth token for Topcoder API v3.
*/
constructor(tokenV3) {
this.private = {
apiV5: getApi('V5', tokenV3),
tokenV3,
};
}
/**
* Get submissions of challenge
* @param {Object} filters
* @param {Object} params
* @return {Promise} Resolves to the api response.
*/
async getSubmissions(filters, params) {
const query = {
...filters,
...params,
};
const url = `/submissions?${qs.stringify(query, { encode: false })}`;
return this.private.apiV5.get(url)
.then(checkErrorV5)
.then(res => res.result);
}
/**
* Get submission artifacts of challenge
* @param {String} submissionId
* @return {Promise} Resolves to the api response.
*/
async getSubmissionArtifacts(submissionId) {
const url = `/submissions/${submissionId}/artifacts`;
return this.private.apiV5.get(url)
.then(checkErrorV5)
.then(res => res.result);
}
/**
* Download submission artifact.
* @param {Number|String} submissionId Submission ID.
* * @param {String} fileName Artifact file name.
* @return {Promise} Resolves to the list of submission object.
*/
async downloadSubmissionArtifact(submissionId, fileName) {
return this.private.apiV5.get(`/submissions/${submissionId}/artifacts/${fileName}/download`)
.then(response => response.blob());
}
/**
* Get scan reviews types
* @returns {Promise} Resolves to the api response.
*/
async getScanReviewIds() {
const reviews = await Promise.all([
this.private.apiV5.get('/reviewTypes?name=AV Scan')
.then(checkErrorV5)
.then(res => res.result),
this.private.apiV5.get('/reviewTypes?name=SonarQube Review')
.then(checkErrorV5)
.then(res => res.result),
this.private.apiV5.get('/reviewTypes?name=Virus Scan')
.then(checkErrorV5)
.then(res => res.result),
]).then(([av, sonar, virus]) => (_.concat(av, sonar, virus)));
return reviews.map(r => r.id);
}
/**
* Get submission information by submission id
* @param submissionId The submission id
* @returns {Promise} Resolves to the api response.
*/
async getSubmissionInformation(submissionId) {
const url = `/submissions/${submissionId}`;
return this.private.apiV5.get(url)
.then(res => (res.ok ? res.json() : new Error(res.statusText)))
.then(res => res);
}
/**
* Download submission.
* @param {Number|String} submissionId Submission ID.
* @return {Promise} Resolves to the list of submission object.
*/
async downloadSubmission(submissionId) {
return this.private.apiV5.get(`/submissions/${submissionId}/download`)
.then(response => response.blob());
}
}
let lastInstance = null;
/**
* Returns a new or existing submissions service.
* @param {String} tokenV3 Optional. Auth token for Topcoder API v3.
* @return {SubmissionsService} Submissions service object
*/
export function getService(tokenV3) {
if (!lastInstance || lastInstance.private.tokenV3 !== tokenV3) {
lastInstance = new SubmissionsService(tokenV3);
}
return lastInstance;
}
/* Using default export would be confusing in this case. */
export default undefined;