UNPKG

wikipathways-api-client

Version:
322 lines 22.3 kB
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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