esearch.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import axios from 'axios'
  2. import genbankParser from 'genbank-parser'
  3. import { XMLParser } from 'fast-xml-parser'
  4. import jsonata from 'jsonata';
  5. const simpleJSON = (json:any):any => {
  6. if (Array.isArray(json)) {
  7. if (json.length === 1) { return simpleJSON(json[0]) }
  8. else { return json }
  9. } else if (typeof json === 'object') {
  10. if (Object.keys(json).length === 1 && typeof json[Object.keys(json)[0]] === 'object') { return simpleJSON(json[Object.keys(json)[0]]) }
  11. else { return json }
  12. } else {
  13. return json
  14. }
  15. }
  16. const renameKeys = (json:any):any => {
  17. if(Array.isArray(json)) {
  18. return json.map(e => renameKeys(e))
  19. } else if (typeof json === 'object') {
  20. const newObj:any = {}
  21. Object.keys(json).map(key => {
  22. let tmp
  23. if(typeof json[key] === 'object') {
  24. tmp = renameKeys(json[key])
  25. } else {
  26. tmp = json[key]
  27. }
  28. newObj[key.replace(/-/g,"_")] = tmp
  29. })
  30. return newObj
  31. } else {
  32. return json
  33. }
  34. }
  35. const getEsearch = async (params: any) => {
  36. const endpoint = params?.endpoint ? params.endpoint : 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi'
  37. const queries = Array.isArray(params?.query) ? params?.query : [params?.query]
  38. params.id = Array.isArray(params?.id) ? params.id.join(',') : params.id
  39. let allowedParams: string[]
  40. let connType: string = 'get'
  41. if (endpoint.match('esearch')) {
  42. allowedParams = ['db', 'term', 'retmax', 'retstart', 'api_key']
  43. params = {...params, retmax: 100000, retmode: 'xml'}
  44. } else if (endpoint.match('efetch')) {
  45. connType = 'get'
  46. allowedParams = ['id', 'db', 'retmode', 'rettype', 'retmax', 'api_key']
  47. const retmode = params?.rettype === 'fasta' || params?.rettype === 'gb'? 'txt' : 'xml'
  48. params = {...params, retmax: 10000, retmode}
  49. } else if (endpoint.match('esummary')) {
  50. allowedParams = ['id', 'db', 'retmode', 'rettype', 'retstart', 'version', 'api_key']
  51. params = {...params, retmax: 10000, retmode: 'xml', version: '2.0'}
  52. }
  53. let response:any = ''
  54. switch (connType) {
  55. case 'post':
  56. let postParam:any = {}
  57. Object.keys(params).flatMap(k => allowedParams.includes(k) ? postParam[k] = params[k] : [])
  58. response = await axios.post(endpoint, postParam)
  59. break;
  60. case 'get':
  61. const q = `${endpoint}?${Object.keys(params).flatMap(k => allowedParams.includes(k) ? k + '=' + params[k] : []).join('&')}`
  62. console.log(q);
  63. let block = 0
  64. let ctrl = true
  65. while(ctrl && block <= 5) {
  66. try {
  67. response = await axios.get(q)
  68. ctrl = false
  69. } catch (error) {}
  70. block++
  71. if(block === 6) {
  72. console.log("Dropping !!! ", q);
  73. }
  74. }
  75. default:
  76. break;
  77. }
  78. let json = Array.isArray(response.data) ? response.data.join('') : response.data
  79. if (params?.retmode) {
  80. switch (params.retmode) {
  81. case 'xml':
  82. const parser = new XMLParser({
  83. ignoreAttributes: false,
  84. alwaysCreateTextNode: false,
  85. attributeNamePrefix: "",
  86. textNodeName: "value",
  87. allowBooleanAttributes: true,
  88. })
  89. json = parser.parse(json)
  90. break;
  91. case 'gb':
  92. json = genbankParser(json)
  93. break;
  94. default:
  95. break;
  96. }
  97. }
  98. json = renameKeys(json)
  99. const results = []
  100. for (const query of queries) {
  101. let result:any
  102. if (query !== '') {
  103. result = {query, value: jsonata(query).evaluate(json)/*simpleJSON(JSONPath({path: query, json})) */}
  104. } else {
  105. result = ''
  106. }
  107. results.push(result)
  108. }
  109. return simpleJSON(results)
  110. }
  111. module.exports = async (params:any) => await getEsearch(params)