From 9149535691eb30fe4206eb3bc32c5643ca181de1 Mon Sep 17 00:00:00 2001 From: Ruben Paz Date: Sun, 30 Apr 2017 14:15:39 +0100 Subject: [PATCH] (#33) [Feature] Do the ncbi valid db checks at lib level Do the db filter at lib level Add tests to valid-dbs Fix identation Istanbul should use all the test files for coverage --- cli.js | 84 ++++++++++++++++++++------------------------- lib/bionode-ncbi.js | 7 ++++ lib/valid-dbs.js | 72 ++++++++++++++++++++++++++++++++++++++ package.json | 6 ++-- test/valid-dbs.js | 27 +++++++++++++++ 5 files changed, 147 insertions(+), 49 deletions(-) create mode 100644 lib/valid-dbs.js create mode 100644 test/valid-dbs.js diff --git a/cli.js b/cli.js index ab7eb95..8dad11f 100755 --- a/cli.js +++ b/cli.js @@ -3,6 +3,8 @@ var JSONStream = require('JSONStream') var split = require('split2') var ncbi = require('./') var insight = require('./lib/anonymous-tracking') +var validDbs = require('./lib/valid-dbs') + var argv = require('yargs') .strict() .demandCommand(1) @@ -75,26 +77,7 @@ bionode-ncbi plink tax sra -s --pretty` .boolean('pretty') .describe('pretty', 'Print human readable output instead of NDJSON') .choices('dlsource', ['assembly', 'sra']) -.choices('db', [ - 'gquery', 'assembly', 'bioproject', 'biosample', 'biosystems', 'books', - 'clinvar', 'clone', 'cdd', 'gap', 'dbvar', 'nucest', 'gene', 'genome', 'gds', - 'geoprofiles', 'nucgss', 'gtr', 'homologene', 'medgen', 'mesh', 'ncbisearch', - 'nlmcatalog', 'nuccore', 'omim', 'pmc', 'popset', 'probe', 'protein', - 'proteinclusters', 'pcassay', 'pccompound', 'pcsubstance', 'pubmed', - 'pubmedhealth', 'snp', 'sparcle', 'sra', 'structure', 'taxonomy', 'toolkit', - 'toolkitall', 'toolkitbook', 'toolkitbookgh', 'unigene' -]) -.example('databases available', -`gquery (All Databases), assembly, bioproject, biosample, biosystems, \ -books, clinvar, clone, cdd (Conserved Domains), gap (dbGaP), dbvar, \ -nucest (EST), gene, genome, gds (GEO DataSets), geoprofiles (GEO Profiles), \ -nucgss (GSS), gtr (GTR), homologene, medgen, mesh, \ -ncbisearch (NCBI Web Site), nlmcatalog, nuccore (Nucleotide), omim, pmc, \ -popset, probe, protein, proteinclusters, pcassay (PubChem BioAssay), \ -pccompound (PubChem Compound), pcsubstance (PubChem Substance), \ -pubmed, pubmedhealth, snp, sparcle, sra, structure, \ -taxonomy, toolkit, toolkitall, toolkitbook, toolkitbookgh, unigene` -) +.example('databases available', validDbs.printDbs()) .example(`DEBUG mode: export DEBUG='*'`) .argv @@ -102,36 +85,45 @@ if (argv.dlsource) { argv.db = argv.dlsource } insight.track('ncbi', 'cli') -var ncbiStream = ncbi[argv._[0]](argv) +try { + var ncbiStream = ncbi[argv._[0]](argv) -var jsonStream -if (argv.pretty) { - jsonStream = JSONStream.stringify(false, null, null, 2) -} else { - jsonStream = JSONStream.stringify(false) -} + var jsonStream + if (argv.pretty) { + jsonStream = JSONStream.stringify(false, null, null, 2) + } else { + jsonStream = JSONStream.stringify(false) + } -ncbiStream.pipe(jsonStream).pipe(process.stdout) + ncbiStream.pipe(jsonStream).pipe(process.stdout) -if (argv.stdin) { - insight.track('ncbi', 'stdin') - process.stdin.setEncoding('utf8') + if (argv.stdin) { + insight.track('ncbi', 'stdin') + process.stdin.setEncoding('utf8') - process.stdin - .pipe(split()) - .pipe(JSONStream.parse()) - .pipe(ncbiStream) + process.stdin + .pipe(split()) + .pipe(JSONStream.parse()) + .pipe(ncbiStream) - process.stdin.on('end', function () { - ncbiStream.end() - }) -} + process.stdin.on('end', function () { + ncbiStream.end() + }) + } -process.stdout.on('error', function (err) { - if (err.code === 'EPIPE') { process.exit(0) } -}) + process.stdout.on('error', function (err) { + if (err.code === 'EPIPE') { process.exit(0) } + }) -ncbiStream.on('error', function (error) { - console.error(error.message) - process.exit() -}) + ncbiStream.on('error', function (error) { + console.error(error.message) + process.exit() + }) +} catch (err) { + if (err instanceof validDbs.InvalidDbError) { + console.error(err.message) + console.log('Run "bionode-ncbi --help" to check the available dbs') + } else { + console.error(err) + } +} diff --git a/lib/bionode-ncbi.js b/lib/bionode-ncbi.js index 7bdec45..bbe0272 100755 --- a/lib/bionode-ncbi.js +++ b/lib/bionode-ncbi.js @@ -40,6 +40,9 @@ var cheerio = require('cheerio') var fasta = require('bionode-fasta') var insight = require('./anonymous-tracking') +var validDbs = require('./valid-dbs') +var InvalidDbError = validDbs.InvalidDbError + var ncbi = exports var PROXY = typeof window !== 'undefined' ? 'http://cors.inb.io/' : '' @@ -111,6 +114,10 @@ ncbi.search = function (db, term, cb) { var opts = typeof db === 'string' ? { db, term } : db cb = typeof term === 'function' ? term : cb + if (Object.keys(validDbs.dbs).indexOf(opts.db) < 0) { + throw new InvalidDbError('The database "' + opts.db + '" is not a valid ncbi database') + } + var stream = pumpify.obj( createAPISearchUrl(opts.db, opts.term), requestStream(true), diff --git a/lib/valid-dbs.js b/lib/valid-dbs.js new file mode 100644 index 0000000..2a9bd47 --- /dev/null +++ b/lib/valid-dbs.js @@ -0,0 +1,72 @@ + +var dbs = { + gquery: 'All Databases', + assembly: 'Assembly', + bioproject: 'BioProject', + biosample: 'BioSample', + biosystems: 'BioSystems', + books: 'Books', + clinvar: 'ClinVar', + clone: 'Clone', + cdd: 'Conserved Domains', + gap: 'dbGaP', + dbvar: 'dbVar', + nucest: 'EST', + gene: 'Gene', + genome: 'Genome', + gds: 'GEO DataSets', + geoprofiles: 'GEO Profiles', + nucgss: 'GSS', + gtr: 'GTR', + homologene: 'HomoloGene', + medgen: 'MedGen', + mesh: 'MeSH', + ncbisearch: 'NCBI Web Site', + nlmcatalog: 'NLM Catalog', + nuccore: 'Nucleotide', + omim: 'OMIM', + pmc: 'PMC', + popset: 'PopSet', + probe: 'Probe', + protein: 'Protein', + proteinclusters: 'Protein Clusters', + pcassay: 'PubChem BioAssay', + pccompound: 'PubChem Compound', + pcsubstance: 'PubChem Substance', + pubmed: 'PubMed', + pubmedhealth: 'PubMed Health', + snp: 'SNP', + sparcle: 'Sparcle', + sra: 'SRA', + structure: 'Structure', + taxonomy: 'Taxonomy', + toolkit: 'ToolKit', + toolkitall: 'ToolKitAll', + toolkitbook: 'ToolKitBook', + toolkitbookgh: 'ToolKitBookgh', + unigene: 'UniGene' +} + +function printDbs (dbsObject) { + dbsObject = dbsObject || dbs + + var keys = Object.keys(dbsObject) + return keys.reduce((acc, k, i) => { + acc = acc + k + ' (' + dbsObject[k] + ')' + if (i < keys.length - 1) { + acc = acc + '\n' + } + return acc + }, '') +} + +function InvalidDbError (msg) { + this.name = 'InvalidDbError' + this.message = msg +} + +InvalidDbError.prototype = new Error('Invalid database') + +module.exports.dbs = dbs +module.exports.InvalidDbError = InvalidDbError +module.exports.printDbs = printDbs diff --git a/package.json b/package.json index 7884ed2..f996ead 100644 --- a/package.json +++ b/package.json @@ -60,10 +60,10 @@ "bionode-ncbi": "cli.js" }, "scripts": { - "test": "standard && dependency-check . && node test/*.js | tap-spec", + "test": "standard && dependency-check . && tape test/**/*.js | tap-spec", "test-browser": "browserify test/*.js -d | testling -x 'open -a \"Google Chrome\"' | tap-spec", - "coverage": "standard && dependency-check . && istanbul cover test/bionode-ncbi.js --report lcovonly -- | tap-spec && rm -rf ./coverage", - "coveralls": "istanbul cover test/bionode-ncbi.js --report lcovonly -- | tap-spec && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls && rm -rf ./coverage", + "coverage": "standard && dependency-check . && istanbul cover tape test/**/*.js --report lcovonly -- | tap-spec && rm -rf ./coverage", + "coveralls": "istanbul cover tape test/**/*.js --report lcovonly -- | tap-spec && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls && rm -rf ./coverage", "build-browser": "browserify -r ./index.js:bionode-ncbi | uglifyjs > bionode-ncbi.min.js", "build-docs": "docco ./lib/bionode-ncbi.js" }, diff --git a/test/valid-dbs.js b/test/valid-dbs.js new file mode 100644 index 0000000..72d534d --- /dev/null +++ b/test/valid-dbs.js @@ -0,0 +1,27 @@ +var tape = require('tape') +var tapeNock = require('tape-nock') +var validDbs = require('../lib/valid-dbs') +var ncbi = require('../lib/bionode-ncbi') + +var test = tapeNock(tape) + +test('valid-dbs printDbs', t => { + var dummy = {fakedb: 'Fake!', another: 'Another'} + + var expected = 'fakedb (Fake!)\nanother (Another)' + + t.equals(validDbs.printDbs(dummy), expected, 'printDbs returns the expected string') + + t.end() +}) + +// TODO move this test to a suite just for bionode-ncbi search +test('bionode-ncbi search', t => { + t.plan(1) + + try { + ncbi.search('invalid', 'human') + } catch (err) { + t.assert(err instanceof validDbs.InvalidDbError, 'call search with wrong db throws InvalidDbError') + } +})