From 3a3b94119deab0bd20ced56b4b928e1d9696362e Mon Sep 17 00:00:00 2001 From: shamseen Date: Fri, 14 May 2021 19:25:48 -0400 Subject: [PATCH 1/4] added axios to call APIs --- package.json | 1 + yarn.lock | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/package.json b/package.json index 1a30483..316066d 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dev": "nodemon server.js" }, "dependencies": { + "axios": "^0.21.1", "cors": "^2.8.5", "dotenv": "^9.0.2", "express": "^4.17.1", diff --git a/yarn.lock b/yarn.lock index 6a55dde..0f02f6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,6 +35,13 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= +axios@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" + integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== + dependencies: + follow-redirects "^1.10.0" + bl@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5" @@ -212,6 +219,11 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" +follow-redirects@^1.10.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" + integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg== + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" From 29a64bde7bd20c356d5a1ba25e2774dfef9c563a Mon Sep 17 00:00:00 2001 From: shamseen Date: Fri, 14 May 2021 19:28:51 -0400 Subject: [PATCH 2/4] ENA: fixed search; used predefined rule in GET #5 --- controllers/searchController.js | 38 +++++++++++++++++++++++++++++++++ dataServices/enaService.js | 37 ++++++++++++++++++++++++++++++++ server.js | 11 +++++----- 3 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 controllers/searchController.js create mode 100644 dataServices/enaService.js diff --git a/controllers/searchController.js b/controllers/searchController.js new file mode 100644 index 0000000..ffae594 --- /dev/null +++ b/controllers/searchController.js @@ -0,0 +1,38 @@ +const express = require('express'); +const router = express.Router(); +const ENAService = require('../dataServices/enaService'); +const ena = new ENAService(); + +// TEST GET! +router.get('/', async (req, res) => { + // const filter = { [req.params.prop]: req.params.val }; + + try { + const found = await ena.getSequences(); + res.status(200).json(found); + + } catch (err) { + console.log(err); + res.status(400).json({ + msg: err.message + }); + } +}); + + +// Show => GET by any prop +router.get('/:prop/:val', async (req, res) => { + // const filter = { [req.params.prop]: req.params.val }; + + try { + const found = await enaService.search(req.params.prop, req.params.val); + res.status(200).json(found); + + } catch (err) { + res.status(400).json({ + msg: err.message + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/dataServices/enaService.js b/dataServices/enaService.js new file mode 100644 index 0000000..49e215c --- /dev/null +++ b/dataServices/enaService.js @@ -0,0 +1,37 @@ +// structure from https://www.codementor.io/@evanbechtol/node-service-oriented-architecture-12vjt9zs9i + +/* -------------------------------------------------------------- */ +// European Nucleotide Archive (ENA): database of sequences +// The European Bioinformatics Institute exposes an API to access ENA +// In ENA, record IDs are called accessions +// ***limiting search to sequence accession number for now +/* -------------------------------------------------------------- */ +const axios = require('axios') + + +class ENAService { + /* - using default constructor - */ + + // limiting to sequence accession number for now. + // static baseURL = 'https://www.ebi.ac.uk/ena/portal/api/search?dataPortal=ena&query='; + static resultLimit = 10; + enaSequence = ''; + enaStudy = ''; + + // calls API using a pre-made rule on their side. + async getSequences() { + try { + const response = await axios.get('https://www.ebi.ac.uk/ena/portal/api/search?rule=pngcat-dna-studies&sortDirection=asc'); + + return response.data; + + } catch (error) { + // console.log(error); + + return error.message; + } + } + +} + +module.exports = ENAService; \ No newline at end of file diff --git a/server.js b/server.js index a153b48..03800c8 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,5 @@ /* --- Required modules --- */ -require('dotenv').config() // inject .env into process.env +require('dotenv').config(); // inject .env into process.env const express = require('express'); // http server const cors = require('cors'); // expose resources for external websites const mongoose = require('mongoose'); // talks to mongo db @@ -14,7 +14,7 @@ mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useCreateIndex: true, useFindAndModify: false -}) +}); // confirm connection mongoose.connection.once('connected', () => console.log('>> mongoose is connected to mongoDB')); @@ -29,11 +29,12 @@ app.use((req, res, next) => { app.use(cors()); // exposes endpoints for apps to request /* --- Routes --- */ -app.use('/pngcats', require('./controllers/pngcatsController')) +app.use('/pngcats', require('./controllers/pngcatsController')); +app.use('/search', require('./controllers/searchController')); app.get('/', (req, res) => { - res.send(`

.pnGCAT API

`) + res.send(`

.pnGCAT API

`); }) /* --- Leggggoooooooo --- */ -app.listen(PORT, () => console.log(`>> API Server: Listening on port ${PORT}. waiting for database...`)) \ No newline at end of file +app.listen(PORT, () => console.log(`>> API Server: Listening on port ${PORT}. waiting for database...`)); \ No newline at end of file From 678fcf932c9bff37713a38cfa3bc6af7824ba03c Mon Sep 17 00:00:00 2001 From: shamseen Date: Fri, 14 May 2021 19:52:25 -0400 Subject: [PATCH 3/4] using unique rule ID instead #5 --- dataServices/enaService.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dataServices/enaService.js b/dataServices/enaService.js index 49e215c..a2d9c55 100644 --- a/dataServices/enaService.js +++ b/dataServices/enaService.js @@ -19,9 +19,10 @@ class ENAService { enaStudy = ''; // calls API using a pre-made rule on their side. + // TODO: use POST endpoint async getSequences() { try { - const response = await axios.get('https://www.ebi.ac.uk/ena/portal/api/search?rule=pngcat-dna-studies&sortDirection=asc'); + const response = await axios.get('https://www.ebi.ac.uk/ena/portal/api/search?rule=8624c855-9921-4b98-b763-ac0d79b6a567'); return response.data; From 20e04acec9dcf00294bfcd9fe9a07a1355af040a Mon Sep 17 00:00:00 2001 From: shamseen Date: Wed, 19 May 2021 16:30:10 -0400 Subject: [PATCH 4/4] filtering results skeleton --- controllers/searchController.js | 16 +++---- dataServices/enaDataService.js | 79 +++++++++++++++++++++++++++++++++ dataServices/enaService.js | 38 ---------------- 3 files changed, 87 insertions(+), 46 deletions(-) create mode 100644 dataServices/enaDataService.js delete mode 100644 dataServices/enaService.js diff --git a/controllers/searchController.js b/controllers/searchController.js index ffae594..2680e56 100644 --- a/controllers/searchController.js +++ b/controllers/searchController.js @@ -1,14 +1,13 @@ const express = require('express'); const router = express.Router(); -const ENAService = require('../dataServices/enaService'); -const ena = new ENAService(); +const ENADataService = require('../dataServices/enaDataService'); +const ena = new ENADataService(); // TEST GET! router.get('/', async (req, res) => { - // const filter = { [req.params.prop]: req.params.val }; try { - const found = await ena.getSequences(); + const found = ena.enaData; res.status(200).json(found); } catch (err) { @@ -19,13 +18,14 @@ router.get('/', async (req, res) => { } }); - -// Show => GET by any prop -router.get('/:prop/:val', async (req, res) => { +// +router.get('/:query', async (req, res) => { // const filter = { [req.params.prop]: req.params.val }; + // TODO: parse query, search mongo too try { - const found = await enaService.search(req.params.prop, req.params.val); + const found = []; + // const found = await enaService.search(); res.status(200).json(found); } catch (err) { diff --git a/dataServices/enaDataService.js b/dataServices/enaDataService.js new file mode 100644 index 0000000..f71ae0e --- /dev/null +++ b/dataServices/enaDataService.js @@ -0,0 +1,79 @@ +// structure from https://www.codementor.io/@evanbechtol/node-service-oriented-architecture-12vjt9zs9i + +/* -------------------------------------------------------------- */ +// European Nucleotide Archive (ENA): database of sequences +// The European Bioinformatics Institute exposes an API to access ENA +// In ENA, record IDs are called accessions +/* -------------------------------------------------------------- */ +const axios = require('axios') + + +class ENADataService { + /* - populating with fixed search on instantiation - */ + constructor() { + this.searchENA(); + } + + /* -- variables for JOINs -- */ + // static baseURL = 'https://www.ebi.ac.uk/ena/portal/api/search?dataPortal=ena&query='; + // static resultLimit = 10; + + /* -- API Calls -- */ + // BLOCKED: ena POST endpoint docs are missing, waiting to hear back + + // using a custom rule i made on their side instead + async searchENA() { + try { + const response = await axios.get('https://www.ebi.ac.uk/ena/portal/api/search?rule=8624c855-9921-4b98-b763-ac0d79b6a567'); + + this.enaData = response.data; // axios returns JSON already + return this.enaData; + + } catch (error) { + // console.log(error); + + return error.message; + } + } + + /* -- Search Functionality -- */ + + filterByAccession(accType, value, arr) { + + } + + filterByKeyword(keyword, arr) { + + } + + search(seq_accession, study_accession, keyword) { + let results = [...this.enaData]; + + if (seq_accession !== '') + results = this.filterByAccession('accession', seq_accession, results); + + if (study_accession !== '') + results = this.filterByAccession('study_accession', study_accession, results); + + if (keyword !== '') + results = this.filterByKeyword(keyword, results); + + return results; + } + + /* Returns array of: + { + "accession": "CP034527", + "study_accession": "PRJNA504496", + "scientific_name": "eukaryotic synthetic construct", + "cell_type": "", + "dataclass": "STD", + "description": "Eukaryotic synthetic construct chromosome 3.", + "mol_type": "other DNA", + "plasmid": "", + "keywords": "" + } + */ +} + +module.exports = ENADataService; \ No newline at end of file diff --git a/dataServices/enaService.js b/dataServices/enaService.js deleted file mode 100644 index a2d9c55..0000000 --- a/dataServices/enaService.js +++ /dev/null @@ -1,38 +0,0 @@ -// structure from https://www.codementor.io/@evanbechtol/node-service-oriented-architecture-12vjt9zs9i - -/* -------------------------------------------------------------- */ -// European Nucleotide Archive (ENA): database of sequences -// The European Bioinformatics Institute exposes an API to access ENA -// In ENA, record IDs are called accessions -// ***limiting search to sequence accession number for now -/* -------------------------------------------------------------- */ -const axios = require('axios') - - -class ENAService { - /* - using default constructor - */ - - // limiting to sequence accession number for now. - // static baseURL = 'https://www.ebi.ac.uk/ena/portal/api/search?dataPortal=ena&query='; - static resultLimit = 10; - enaSequence = ''; - enaStudy = ''; - - // calls API using a pre-made rule on their side. - // TODO: use POST endpoint - async getSequences() { - try { - const response = await axios.get('https://www.ebi.ac.uk/ena/portal/api/search?rule=8624c855-9921-4b98-b763-ac0d79b6a567'); - - return response.data; - - } catch (error) { - // console.log(error); - - return error.message; - } - } - -} - -module.exports = ENAService; \ No newline at end of file