wikipathways-api-client
Version:
JS client for the WikiPathways.org webservices API
322 lines • 22.3 kB
JavaScript
import * as atobPolyfill from 'atob';
import * as mediaTypes from './media-types';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/dom/ajax';
import 'rxjs/add/observable/from';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/zip';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import * as URI from 'urijs';
import * as XMLResponseParsers from './XMLResponseParsers';
;
;
;
if (!global.hasOwnProperty('XMLHttpRequest')) {
global.XMLHttpRequest = require('xhr2');
}
if (!global.hasOwnProperty('atob')) {
global.atob = atobPolyfill;
}
var convertObjectToQueryString = function (inputObject) {
var str = '';
for (let 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
*/
export class WikipathwaysApiClient {
constructor({ baseIri, timeout } = { baseIri: null, timeout: 10 * 1000 }) {
this.SUPPORTED = mediaTypes.SUPPORTED;
this.timeout = timeout;
if (!baseIri) {
const 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.
*/
getPathway({ identifier, version, fileFormat } = {
identifier: undefined, version: 0, fileFormat: 'application/ld+json'
}) {
if (!identifier) {
throw new Error('Please provide identifier');
}
const mediaType = mediaTypes.REQUESTED_TO_IANA_FOR_PATHWAYS[fileFormat.toLowerCase()];
const iri = URI(this.baseIri)
.filename('getPathwayAs')
.query({
pwId: identifier,
fileType: mediaTypes.IANA_TO_WP_API_BODY[mediaType],
revision: version || 0,
format: 'json'
});
let pathwayMetadata = {};
pathwayMetadata['@id'] = 'http://identifiers.org/wikipathways/' + identifier;
pathwayMetadata.version = version;
const ajaxRequest = {
url: iri.toString(),
method: 'GET',
responseType: 'json',
timeout: this.timeout,
crossDomain: true,
};
return Observable.ajax(ajaxRequest)
.map((ajaxResponse) => ajaxResponse.xhr.response)
.map(function (response) {
return atob(response.data).toString();
});
}
getPathwayInfo(identifier) {
if (!identifier) {
throw new Error('Please provide identifier');
}
const iri = URI(this.baseIri)
.filename('getPathwayInfo')
.query({
pwId: identifier,
format: 'json',
});
const ajaxRequest = {
url: iri.toString(),
method: 'GET',
responseType: 'json',
timeout: this.timeout,
crossDomain: true,
};
return Observable.ajax(ajaxRequest)
.map((ajaxResponse) => 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;
// });
// }
listPathways() {
const iri = URI(this.baseIri)
.filename('listPathways')
.query({
format: 'json'
});
const ajaxRequest = {
url: iri.toString(),
method: 'GET',
responseType: 'json',
timeout: this.timeout,
crossDomain: true,
};
return Observable.ajax(ajaxRequest)
.map((ajaxResponse) => ajaxResponse.xhr.response)
.mergeMap(function (x) {
return 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.
*/
login({ username, password }) {
const iri = URI(this.baseIri)
.filename('login')
.query({
name: username,
pass: password,
format: 'json',
});
const ajaxRequest = {
url: iri.toString(),
method: 'GET',
responseType: 'json',
timeout: this.timeout,
crossDomain: true,
};
return Observable.ajax(ajaxRequest)
.map((ajaxResponse) => ajaxResponse.xhr.response)
.map(function (data) {
if (!data.hasOwnProperty('auth')) {
return Observable.throw(new Error('Login problem. No auth property on response body.'));
}
else {
return data.auth;
}
});
}
updatePathway({ description, username, password, identifier, gpml }) {
const baseIri = this.baseIri;
const gpmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
const prefixedGpml = (gpml.indexOf(gpmlHeader) === 0 ? '' : gpmlHeader).concat(gpml);
return Observable.zip(this.login({ username: username, password: password }), this.getPathwayInfo(identifier))
.mergeMap(function ([loginResult, pathwayInfo]) {
const iri = URI(baseIri)
.filename('updatePathway');
const 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.ajax(ajaxRequest)
.mergeMap(XMLResponseParsers.updatePathway)
.map(function (response) {
const { status, statusText, message } = response;
let output = {
status: status,
statusText: statusText,
};
const outputStatus = output.status;
if (200 <= outputStatus && outputStatus < 300) {
output.version = parseInt(message);
}
else {
output.error = message;
}
return output;
});
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lraXBhdGh3YXlzLWFwaS1jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd2lraXBhdGh3YXlzLWFwaS1jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLFlBQVksTUFBTSxNQUFNLENBQUM7QUFDckMsT0FBTyxLQUFLLFVBQVUsTUFBTSxlQUFlLENBQUM7QUFDNUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTdDLE9BQU8sOEJBQThCLENBQUM7QUFDdEMsT0FBTywwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLDJCQUEyQixDQUFDO0FBQ25DLE9BQU8seUJBQXlCLENBQUM7QUFDakMsT0FBTyxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUM7QUFDN0IsT0FBTyxLQUFLLGtCQUFrQixNQUFNLHNCQUFzQixDQUFDO0FBK0MxRCxDQUFDO0FBR0QsQ0FBQztBQUdELENBQUM7QUFHRixJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFO0lBQzdDLE1BQU0sQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0NBQ3hDO0FBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUU7SUFDbkMsTUFBTSxDQUFDLElBQUksR0FBRyxZQUFZLENBQUM7Q0FDM0I7QUFFRCxJQUFJLDBCQUEwQixHQUFHLFVBQVMsV0FBVztJQUNuRCxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFFYixLQUFLLElBQUksR0FBRyxJQUFJLFdBQVcsRUFBRTtRQUMzQixJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsSUFBSSxPQUFPLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxV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