wikipathways-api-client
Version:
JS client for the WikiPathways.org webservices API
331 lines • 23 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var atobPolyfill = require("atob");
var mediaTypes = require("./media-types");
var Observable_1 = require("rxjs/Observable");
require("rxjs/add/observable/dom/ajax");
require("rxjs/add/observable/from");
require("rxjs/add/observable/throw");
require("rxjs/add/observable/zip");
require("rxjs/add/operator/do");
require("rxjs/add/operator/map");
require("rxjs/add/operator/mergeMap");
var URI = require("urijs");
var XMLResponseParsers = require("./XMLResponseParsers");
;
;
;
if (!global.hasOwnProperty('XMLHttpRequest')) {
global.XMLHttpRequest = require('xhr2');
}
if (!global.hasOwnProperty('atob')) {
global.atob = atobPolyfill;
}
var convertObjectToQueryString = function (inputObject) {
var str = '';
for (var key in inputObject) {
if (!inputObject.hasOwnProperty(key) || typeof inputObject[key] === 'function') {
continue;
}
if (typeof inputObject[key] === 'object') {
str += convertObjectToQueryString(inputObject[key]);
}
else {
str += key + '=' + encodeURIComponent(inputObject[key]) + '&';
}
}
return str;
};
/**
* WikipathwaysApiClient
*
* @param args
*/
var WikipathwaysApiClient = /** @class */ (function () {
function WikipathwaysApiClient(_a) {
var _b = _a === void 0 ? { baseIri: null, timeout: 10 * 1000 } : _a, baseIri = _b.baseIri, timeout = _b.timeout;
this.SUPPORTED = mediaTypes.SUPPORTED;
this.timeout = timeout;
if (!baseIri) {
var isBrowser = (typeof window !== 'undefined' && typeof document !== 'undefined');
if (isBrowser) {
var hostnameSplit = window.location.hostname.split('wikipathways.org');
if (hostnameSplit[hostnameSplit.length - 1] === '') {
// user is on wikipathways.org or one of its subdomains
baseIri = window.location.origin + '/wpi/webservicetest/';
//baseIri = 'https://webservice.wikipathways.org/'; //this route will lose authentication
// const subdomain = hostnameSplit[0];
// if (['','www.'].indexOf(subdomain) > -1) {
// // user is one wikipathways.org main site
// baseIri = window.location.origin + '/wpi/webservicetest/';
// //baseIri = 'https://webservice.wikipathways.org/'; //this route will lose authentication
// } else {
// // user is on a wikipathways.org subdomain (likely a test server).
// // TODO what should the permanent IRI be for the test servers?
// baseIri = window.location.origin + '/wpi/webservicetest/';
// }
}
else {
baseIri = 'https://webservice.wikipathways.org/';
}
}
else {
baseIri = 'https://webservice.wikipathways.org/';
}
}
this.baseIri = baseIri;
}
/**
* getPathway
* NOTE: this actually corresponds to the webservice method "getPathwayAs"
*
* @param args
* @return An Observable with the requested data.
*/
WikipathwaysApiClient.prototype.getPathway = function (_a) {
var _b = _a === void 0 ? {
identifier: undefined, version: 0, fileFormat: 'application/ld+json'
} : _a, identifier = _b.identifier, version = _b.version, fileFormat = _b.fileFormat;
if (!identifier) {
throw new Error('Please provide identifier');
}
var mediaType = mediaTypes.REQUESTED_TO_IANA_FOR_PATHWAYS[fileFormat.toLowerCase()];
var iri = URI(this.baseIri)
.filename('getPathwayAs')
.query({
pwId: identifier,
fileType: mediaTypes.IANA_TO_WP_API_BODY[mediaType],
revision: version || 0,
format: 'json'
});
var pathwayMetadata = {};
pathwayMetadata['@id'] = 'http://identifiers.org/wikipathways/' + identifier;
pathwayMetadata.version = version;
var ajaxRequest = {
url: iri.toString(),
method: 'GET',
responseType: 'json',
timeout: this.timeout,
crossDomain: true,
};
return Observable_1.Observable.ajax(ajaxRequest)
.map(function (ajaxResponse) { return ajaxResponse.xhr.response; })
.map(function (response) {
return atob(response.data).toString();
});
};
WikipathwaysApiClient.prototype.getPathwayInfo = function (identifier) {
if (!identifier) {
throw new Error('Please provide identifier');
}
var iri = URI(this.baseIri)
.filename('getPathwayInfo')
.query({
pwId: identifier,
format: 'json',
});
var ajaxRequest = {
url: iri.toString(),
method: 'GET',
responseType: 'json',
timeout: this.timeout,
crossDomain: true,
};
return Observable_1.Observable.ajax(ajaxRequest)
.map(function (ajaxResponse) { return ajaxResponse.xhr.response.pathwayInfo; })
.map(function (pathwayInfo) {
return {
identifier: pathwayInfo.id,
url: pathwayInfo.url,
name: pathwayInfo.name,
organism: pathwayInfo.species,
version: pathwayInfo.revision,
};
});
};
//import 'rx-extra/add/operator/throughNodeStream';
//import 'rx-extra/add/observable/fromNodeReadableStream';
//const JSONStream = require('JSONStream');
// function listPathways1(args, responseType) {
// args = args || {};
//
// var requestedFileFormat = args.fileFormat || 'application/ld+json';
//
// var mediaType = REQUESTED_TO_IANA[
// requestedFileFormat.toLowerCase()];
//
// if (mediaType !== 'application/ld+json' &&
// mediaType !== 'application/json') {
// throw new Error('Requested file format not recognized or not available.');
// }
//
// var iri = URI(baseIri)
// .filename('listPathways')
// .query({
// format: mediaTypes.IANA_TO_WP_API_ENVELOPE[mediaType]
// });
//
// const ajaxRequest: AjaxRequest = {
// url: iri.toString(),
// method: 'GET',
// responseType: 'text',
// timeout: this.timeout,
// crossDomain: true,
// };
// return Observable.ajax(ajaxRequest)
// .map((ajaxResponse): string => ajaxResponse.xhr.response)
// .throughNodeStream(JSONStream.parse('pathways.*'))
// .map(function(data) {
// var pathway = {
// '@context': [
// 'https://wikipathwayscontexts.firebaseio.com/biopax.json',
// 'https://wikipathwayscontexts.firebaseio.com/organism.json',
// {
// '@vocab': 'http://www.biopax.org/release/biopax-level3.owl#'
// }
// ],
// '@id': 'http://identifiers.org/wikipathways/' + data.id,
// db: 'wikipathways',
// identifier: data.id,
// name: data.name,
// webPage: data.url,
// version: data.revision,
// organism: data.species
// };
//
// return pathway;
// });
// }
WikipathwaysApiClient.prototype.listPathways = function () {
var iri = URI(this.baseIri)
.filename('listPathways')
.query({
format: 'json'
});
var ajaxRequest = {
url: iri.toString(),
method: 'GET',
responseType: 'json',
timeout: this.timeout,
crossDomain: true,
};
return Observable_1.Observable.ajax(ajaxRequest)
.map(function (ajaxResponse) { return ajaxResponse.xhr.response; })
.mergeMap(function (x) {
return Observable_1.Observable.from(x.pathways);
})
.map(function (data) {
return {
'@context': [
'https://wikipathwayscontexts.firebaseio.com/biopax.json',
'https://wikipathwayscontexts.firebaseio.com/organism.json',
{
'@vocab': 'http://www.biopax.org/release/biopax-level3.owl#'
}
],
'@id': 'http://identifiers.org/wikipathways/' + data.id,
db: 'wikipathways',
identifier: data.id,
name: data.name,
webPage: data.url,
version: data.revision,
organism: data.species
};
});
};
/**
* login
*
* @param args If user is visiting a WikiPathways MediaWiki instance via browser and
* is logged in, username and password are optional, because Nuno is
* using cookie-based authentication for the webservice for this case.
* @return An Observable with a token that can be used to make protected requests.
*/
WikipathwaysApiClient.prototype.login = function (_a) {
var username = _a.username, password = _a.password;
var iri = URI(this.baseIri)
.filename('login')
.query({
name: username,
pass: password,
format: 'json',
});
var ajaxRequest = {
url: iri.toString(),
method: 'GET',
responseType: 'json',
timeout: this.timeout,
crossDomain: true,
};
return Observable_1.Observable.ajax(ajaxRequest)
.map(function (ajaxResponse) { return ajaxResponse.xhr.response; })
.map(function (data) {
if (!data.hasOwnProperty('auth')) {
return Observable_1.Observable.throw(new Error('Login problem. No auth property on response body.'));
}
else {
return data.auth;
}
});
};
WikipathwaysApiClient.prototype.updatePathway = function (_a) {
var description = _a.description, username = _a.username, password = _a.password, identifier = _a.identifier, gpml = _a.gpml;
var baseIri = this.baseIri;
var gpmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
var prefixedGpml = (gpml.indexOf(gpmlHeader) === 0 ? '' : gpmlHeader).concat(gpml);
return Observable_1.Observable.zip(this.login({ username: username, password: password }), this.getPathwayInfo(identifier))
.mergeMap(function (_a) {
var loginResult = _a[0], pathwayInfo = _a[1];
var iri = URI(baseIri)
.filename('updatePathway');
var ajaxRequest = {
url: iri.toString(),
method: 'POST',
// 'document' appears to work in Chrome
// and in Node.JS, but
// RxJS4 doesn't support 'document', and
// RxJS5 doesn't have good documentation
// for accepted values here. The value
// 'xml' also appeared to work, but there
// was a warning saying it wasn't in the
// enum of accepted values.
// TODO be sure 'document' is correct and
// works cross browser.
responseType: 'document',
timeout: this.timeout,
crossDomain: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: convertObjectToQueryString({
pwId: identifier,
description: description,
revision: pathwayInfo.version,
gpml: prefixedGpml,
username: username,
auth: loginResult,
}),
};
return Observable_1.Observable.ajax(ajaxRequest)
.mergeMap(XMLResponseParsers.updatePathway)
.map(function (response) {
var status = response.status, statusText = response.statusText, message = response.message;
var output = {
status: status,
statusText: statusText,
};
var outputStatus = output.status;
if (200 <= outputStatus && outputStatus < 300) {
output.version = parseInt(message);
}
else {
output.error = message;
}
return output;
});
});
};
return WikipathwaysApiClient;
}());
exports.WikipathwaysApiClient = WikipathwaysApiClient;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lraXBhdGh3YXlzLWFwaS1jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd2lraXBhdGh3YXlzLWFwaS1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxtQ0FBcUM7QUFDckMsMENBQTRDO0FBQzVDLDhDQUE2QztBQUU3Qyx3Q0FBc0M7QUFDdEMsb0NBQWtDO0FBQ2xDLHFDQUFtQztBQUNuQyxtQ0FBaUM7QUFDakMsZ0NBQThCO0FBQzlCLGlDQUErQjtBQUMvQixzQ0FBb0M7QUFDcEMsMkJBQTZCO0FBQzdCLHlEQUEyRDtBQStDMUQsQ0FBQztBQUdELENBQUM7QUFHRCxDQUFDO0FBR0YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtJQUM3QyxNQUFNLENBQUMsY0FBYyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztDQUN4QztBQUNELElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFO0lBQ25DLE1BQU0sQ0FBQyxJQUFJLEdBQUcsWUFBWSxDQUFDO0NBQzNCO0FBRUQsSUFBSSwwQkFBMEIsR0FBRyxVQUFTLFdBQVc7SUFDbkQsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO0lBRWIsS0FBSyxJQUFJLEdBQUcsSUFBSSxXQUFXLEVBQUU7UUFDM0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLElBQUksT0FBTyxXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssVUFBVSxFQUFFO1lBQUUsU0FBUztTQUFFO1FBQzdGLElBQUksT0FBTyxXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssUUFBUSxFQUFFO1lBQ3hDLEdBQUcsSUFBSSwwQkFBMEIsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztTQUNyRDthQUFNO1lBQ0wsR0FBRyxJQUFJLEdBQUcsR0FBRyxHQUFHLEdBQUcsa0JBQWtCLENBQUMsV0FB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