@ncukondo/search-hub 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/_virtual/___vite-browser-external.js +7 -0
  4. package/dist/_virtual/___vite-browser-external.js.map +1 -0
  5. package/dist/_virtual/__vite-browser-external.js +5 -0
  6. package/dist/_virtual/__vite-browser-external.js.map +1 -0
  7. package/dist/_virtual/_commonjsHelpers.js +28 -0
  8. package/dist/_virtual/_commonjsHelpers.js.map +1 -0
  9. package/dist/_virtual/cli-progress.js +6 -0
  10. package/dist/_virtual/cli-progress.js.map +1 -0
  11. package/dist/_virtual/index.js +5 -0
  12. package/dist/_virtual/index.js.map +1 -0
  13. package/dist/_virtual/index2.js +5 -0
  14. package/dist/_virtual/index2.js.map +1 -0
  15. package/dist/cli/commands/config.d.ts +37 -0
  16. package/dist/cli/commands/config.d.ts.map +1 -0
  17. package/dist/cli/commands/config.js +117 -0
  18. package/dist/cli/commands/config.js.map +1 -0
  19. package/dist/cli/commands/export.d.ts +26 -0
  20. package/dist/cli/commands/export.d.ts.map +1 -0
  21. package/dist/cli/commands/export.js +86 -0
  22. package/dist/cli/commands/export.js.map +1 -0
  23. package/dist/cli/commands/init.d.ts +45 -0
  24. package/dist/cli/commands/init.d.ts.map +1 -0
  25. package/dist/cli/commands/init.js +134 -0
  26. package/dist/cli/commands/init.js.map +1 -0
  27. package/dist/cli/commands/query/translate.d.ts +32 -0
  28. package/dist/cli/commands/query/translate.d.ts.map +1 -0
  29. package/dist/cli/commands/query/translate.js +76 -0
  30. package/dist/cli/commands/query/translate.js.map +1 -0
  31. package/dist/cli/commands/query/validate.d.ts +25 -0
  32. package/dist/cli/commands/query/validate.d.ts.map +1 -0
  33. package/dist/cli/commands/query/validate.js +68 -0
  34. package/dist/cli/commands/query/validate.js.map +1 -0
  35. package/dist/cli/commands/register.d.ts +39 -0
  36. package/dist/cli/commands/register.d.ts.map +1 -0
  37. package/dist/cli/commands/register.js +78 -0
  38. package/dist/cli/commands/register.js.map +1 -0
  39. package/dist/cli/commands/resume-executor.d.ts +19 -0
  40. package/dist/cli/commands/resume-executor.d.ts.map +1 -0
  41. package/dist/cli/commands/resume-executor.js +170 -0
  42. package/dist/cli/commands/resume-executor.js.map +1 -0
  43. package/dist/cli/commands/resume.d.ts +26 -0
  44. package/dist/cli/commands/resume.d.ts.map +1 -0
  45. package/dist/cli/commands/resume.js +51 -0
  46. package/dist/cli/commands/resume.js.map +1 -0
  47. package/dist/cli/commands/search-executor.d.ts +26 -0
  48. package/dist/cli/commands/search-executor.d.ts.map +1 -0
  49. package/dist/cli/commands/search-executor.js +315 -0
  50. package/dist/cli/commands/search-executor.js.map +1 -0
  51. package/dist/cli/commands/search.d.ts +30 -0
  52. package/dist/cli/commands/search.d.ts.map +1 -0
  53. package/dist/cli/commands/search.js +67 -0
  54. package/dist/cli/commands/search.js.map +1 -0
  55. package/dist/cli/commands/status.d.ts +41 -0
  56. package/dist/cli/commands/status.d.ts.map +1 -0
  57. package/dist/cli/commands/status.js +123 -0
  58. package/dist/cli/commands/status.js.map +1 -0
  59. package/dist/cli/e2e-helpers.d.ts +165 -0
  60. package/dist/cli/e2e-helpers.d.ts.map +1 -0
  61. package/dist/cli/exit-codes.d.ts +25 -0
  62. package/dist/cli/exit-codes.d.ts.map +1 -0
  63. package/dist/cli/exit-codes.js +18 -0
  64. package/dist/cli/exit-codes.js.map +1 -0
  65. package/dist/cli/index.d.ts +25 -0
  66. package/dist/cli/index.d.ts.map +1 -0
  67. package/dist/cli/index.js +638 -0
  68. package/dist/cli/index.js.map +1 -0
  69. package/dist/cli/utils/progress.d.ts +24 -0
  70. package/dist/cli/utils/progress.d.ts.map +1 -0
  71. package/dist/cli/utils/progress.js +128 -0
  72. package/dist/cli/utils/progress.js.map +1 -0
  73. package/dist/cli/utils/sessions-dir.d.ts +14 -0
  74. package/dist/cli/utils/sessions-dir.d.ts.map +1 -0
  75. package/dist/cli/utils/sessions-dir.js +21 -0
  76. package/dist/cli/utils/sessions-dir.js.map +1 -0
  77. package/dist/cli/utils/validation.d.ts +18 -0
  78. package/dist/cli/utils/validation.d.ts.map +1 -0
  79. package/dist/cli/utils/validation.js +24 -0
  80. package/dist/cli/utils/validation.js.map +1 -0
  81. package/dist/config/defaults.d.ts +12 -0
  82. package/dist/config/defaults.d.ts.map +1 -0
  83. package/dist/config/defaults.js +10 -0
  84. package/dist/config/defaults.js.map +1 -0
  85. package/dist/config/env.d.ts +12 -0
  86. package/dist/config/env.d.ts.map +1 -0
  87. package/dist/config/env.js +36 -0
  88. package/dist/config/env.js.map +1 -0
  89. package/dist/config/index.d.ts +9 -0
  90. package/dist/config/index.d.ts.map +1 -0
  91. package/dist/config/loader.d.ts +49 -0
  92. package/dist/config/loader.d.ts.map +1 -0
  93. package/dist/config/loader.js +72 -0
  94. package/dist/config/loader.js.map +1 -0
  95. package/dist/config/paths.d.ts +23 -0
  96. package/dist/config/paths.d.ts.map +1 -0
  97. package/dist/config/paths.js +22 -0
  98. package/dist/config/paths.js.map +1 -0
  99. package/dist/config/schema.d.ts +109 -0
  100. package/dist/config/schema.d.ts.map +1 -0
  101. package/dist/config/schema.js +74 -0
  102. package/dist/config/schema.js.map +1 -0
  103. package/dist/index.d.ts +11 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +54 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/integration/ref-cli.d.ts +41 -0
  108. package/dist/integration/ref-cli.d.ts.map +1 -0
  109. package/dist/integration/ref-cli.js +132 -0
  110. package/dist/integration/ref-cli.js.map +1 -0
  111. package/dist/integration/register.d.ts +27 -0
  112. package/dist/integration/register.d.ts.map +1 -0
  113. package/dist/integration/register.js +108 -0
  114. package/dist/integration/register.js.map +1 -0
  115. package/dist/integration/types.d.ts +61 -0
  116. package/dist/integration/types.d.ts.map +1 -0
  117. package/dist/integration/types.js +61 -0
  118. package/dist/integration/types.js.map +1 -0
  119. package/dist/node_modules/cli-progress/cli-progress.js +37 -0
  120. package/dist/node_modules/cli-progress/cli-progress.js.map +1 -0
  121. package/dist/node_modules/cli-progress/lib/eta.js +52 -0
  122. package/dist/node_modules/cli-progress/lib/eta.js.map +1 -0
  123. package/dist/node_modules/cli-progress/lib/format-bar.js +16 -0
  124. package/dist/node_modules/cli-progress/lib/format-bar.js.map +1 -0
  125. package/dist/node_modules/cli-progress/lib/format-time.js +32 -0
  126. package/dist/node_modules/cli-progress/lib/format-time.js.map +1 -0
  127. package/dist/node_modules/cli-progress/lib/format-value.js +25 -0
  128. package/dist/node_modules/cli-progress/lib/format-value.js.map +1 -0
  129. package/dist/node_modules/cli-progress/lib/formatter.js +57 -0
  130. package/dist/node_modules/cli-progress/lib/formatter.js.map +1 -0
  131. package/dist/node_modules/cli-progress/lib/generic-bar.js +137 -0
  132. package/dist/node_modules/cli-progress/lib/generic-bar.js.map +1 -0
  133. package/dist/node_modules/cli-progress/lib/multi-bar.js +147 -0
  134. package/dist/node_modules/cli-progress/lib/multi-bar.js.map +1 -0
  135. package/dist/node_modules/cli-progress/lib/options.js +59 -0
  136. package/dist/node_modules/cli-progress/lib/options.js.map +1 -0
  137. package/dist/node_modules/cli-progress/lib/single-bar.js +95 -0
  138. package/dist/node_modules/cli-progress/lib/single-bar.js.map +1 -0
  139. package/dist/node_modules/cli-progress/lib/terminal.js +125 -0
  140. package/dist/node_modules/cli-progress/lib/terminal.js.map +1 -0
  141. package/dist/node_modules/cli-progress/node_modules/ansi-regex/index.js +18 -0
  142. package/dist/node_modules/cli-progress/node_modules/ansi-regex/index.js.map +1 -0
  143. package/dist/node_modules/cli-progress/node_modules/emoji-regex/index.js +14 -0
  144. package/dist/node_modules/cli-progress/node_modules/emoji-regex/index.js.map +1 -0
  145. package/dist/node_modules/cli-progress/node_modules/string-width/index.js +44 -0
  146. package/dist/node_modules/cli-progress/node_modules/string-width/index.js.map +1 -0
  147. package/dist/node_modules/cli-progress/node_modules/strip-ansi/index.js +14 -0
  148. package/dist/node_modules/cli-progress/node_modules/strip-ansi/index.js.map +1 -0
  149. package/dist/node_modules/cli-progress/presets/index.js +25 -0
  150. package/dist/node_modules/cli-progress/presets/index.js.map +1 -0
  151. package/dist/node_modules/cli-progress/presets/legacy.js +16 -0
  152. package/dist/node_modules/cli-progress/presets/legacy.js.map +1 -0
  153. package/dist/node_modules/cli-progress/presets/rect.js +16 -0
  154. package/dist/node_modules/cli-progress/presets/rect.js.map +1 -0
  155. package/dist/node_modules/cli-progress/presets/shades-classic.js +16 -0
  156. package/dist/node_modules/cli-progress/presets/shades-classic.js.map +1 -0
  157. package/dist/node_modules/cli-progress/presets/shades-grey.js +16 -0
  158. package/dist/node_modules/cli-progress/presets/shades-grey.js.map +1 -0
  159. package/dist/node_modules/env-paths/index.js +58 -0
  160. package/dist/node_modules/env-paths/index.js.map +1 -0
  161. package/dist/node_modules/fast-xml-parser/src/ignoreAttributes.js +22 -0
  162. package/dist/node_modules/fast-xml-parser/src/ignoreAttributes.js.map +1 -0
  163. package/dist/node_modules/fast-xml-parser/src/util.js +33 -0
  164. package/dist/node_modules/fast-xml-parser/src/util.js.map +1 -0
  165. package/dist/node_modules/fast-xml-parser/src/validator.js +309 -0
  166. package/dist/node_modules/fast-xml-parser/src/validator.js.map +1 -0
  167. package/dist/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js +265 -0
  168. package/dist/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js.map +1 -0
  169. package/dist/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js +53 -0
  170. package/dist/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js.map +1 -0
  171. package/dist/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js +515 -0
  172. package/dist/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js.map +1 -0
  173. package/dist/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js +68 -0
  174. package/dist/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js.map +1 -0
  175. package/dist/node_modules/fast-xml-parser/src/xmlparser/node2json.js +88 -0
  176. package/dist/node_modules/fast-xml-parser/src/xmlparser/node2json.js.map +1 -0
  177. package/dist/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js +36 -0
  178. package/dist/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js.map +1 -0
  179. package/dist/node_modules/is-fullwidth-code-point/index.js +37 -0
  180. package/dist/node_modules/is-fullwidth-code-point/index.js.map +1 -0
  181. package/dist/node_modules/strnum/strnum.js +100 -0
  182. package/dist/node_modules/strnum/strnum.js.map +1 -0
  183. package/dist/providers/arxiv/client.d.ts +54 -0
  184. package/dist/providers/arxiv/client.d.ts.map +1 -0
  185. package/dist/providers/arxiv/client.js +105 -0
  186. package/dist/providers/arxiv/client.js.map +1 -0
  187. package/dist/providers/arxiv/index.d.ts +14 -0
  188. package/dist/providers/arxiv/index.d.ts.map +1 -0
  189. package/dist/providers/arxiv/parser.d.ts +16 -0
  190. package/dist/providers/arxiv/parser.d.ts.map +1 -0
  191. package/dist/providers/arxiv/parser.js +144 -0
  192. package/dist/providers/arxiv/parser.js.map +1 -0
  193. package/dist/providers/arxiv/provider.d.ts +39 -0
  194. package/dist/providers/arxiv/provider.d.ts.map +1 -0
  195. package/dist/providers/arxiv/provider.js +153 -0
  196. package/dist/providers/arxiv/provider.js.map +1 -0
  197. package/dist/providers/arxiv/translator.d.ts +17 -0
  198. package/dist/providers/arxiv/translator.d.ts.map +1 -0
  199. package/dist/providers/arxiv/translator.js +112 -0
  200. package/dist/providers/arxiv/translator.js.map +1 -0
  201. package/dist/providers/arxiv/types.d.ts +71 -0
  202. package/dist/providers/arxiv/types.d.ts.map +1 -0
  203. package/dist/providers/arxiv/types.js +17 -0
  204. package/dist/providers/arxiv/types.js.map +1 -0
  205. package/dist/providers/base/index.d.ts +16 -0
  206. package/dist/providers/base/index.d.ts.map +1 -0
  207. package/dist/providers/base/mock-provider.d.ts +76 -0
  208. package/dist/providers/base/mock-provider.d.ts.map +1 -0
  209. package/dist/providers/base/mock-provider.js +159 -0
  210. package/dist/providers/base/mock-provider.js.map +1 -0
  211. package/dist/providers/base/provider.d.ts +95 -0
  212. package/dist/providers/base/provider.d.ts.map +1 -0
  213. package/dist/providers/base/provider.js +117 -0
  214. package/dist/providers/base/provider.js.map +1 -0
  215. package/dist/providers/base/rate-limiter.d.ts +70 -0
  216. package/dist/providers/base/rate-limiter.d.ts.map +1 -0
  217. package/dist/providers/base/rate-limiter.js +111 -0
  218. package/dist/providers/base/rate-limiter.js.map +1 -0
  219. package/dist/providers/base/registry.d.ts +52 -0
  220. package/dist/providers/base/registry.d.ts.map +1 -0
  221. package/dist/providers/base/registry.js +55 -0
  222. package/dist/providers/base/registry.js.map +1 -0
  223. package/dist/providers/base/types.d.ts +163 -0
  224. package/dist/providers/base/types.d.ts.map +1 -0
  225. package/dist/providers/base/types.js +29 -0
  226. package/dist/providers/base/types.js.map +1 -0
  227. package/dist/providers/eric/client.d.ts +40 -0
  228. package/dist/providers/eric/client.d.ts.map +1 -0
  229. package/dist/providers/eric/client.js +93 -0
  230. package/dist/providers/eric/client.js.map +1 -0
  231. package/dist/providers/eric/index.d.ts +14 -0
  232. package/dist/providers/eric/index.d.ts.map +1 -0
  233. package/dist/providers/eric/parser.d.ts +21 -0
  234. package/dist/providers/eric/parser.d.ts.map +1 -0
  235. package/dist/providers/eric/parser.js +86 -0
  236. package/dist/providers/eric/parser.js.map +1 -0
  237. package/dist/providers/eric/provider.d.ts +59 -0
  238. package/dist/providers/eric/provider.d.ts.map +1 -0
  239. package/dist/providers/eric/provider.js +166 -0
  240. package/dist/providers/eric/provider.js.map +1 -0
  241. package/dist/providers/eric/translator.d.ts +12 -0
  242. package/dist/providers/eric/translator.d.ts.map +1 -0
  243. package/dist/providers/eric/translator.js +81 -0
  244. package/dist/providers/eric/translator.js.map +1 -0
  245. package/dist/providers/eric/types.d.ts +84 -0
  246. package/dist/providers/eric/types.d.ts.map +1 -0
  247. package/dist/providers/pubmed/client.d.ts +54 -0
  248. package/dist/providers/pubmed/client.d.ts.map +1 -0
  249. package/dist/providers/pubmed/client.js +141 -0
  250. package/dist/providers/pubmed/client.js.map +1 -0
  251. package/dist/providers/pubmed/index.d.ts +27 -0
  252. package/dist/providers/pubmed/index.d.ts.map +1 -0
  253. package/dist/providers/pubmed/parser.d.ts +22 -0
  254. package/dist/providers/pubmed/parser.d.ts.map +1 -0
  255. package/dist/providers/pubmed/parser.js +174 -0
  256. package/dist/providers/pubmed/parser.js.map +1 -0
  257. package/dist/providers/pubmed/provider.d.ts +44 -0
  258. package/dist/providers/pubmed/provider.d.ts.map +1 -0
  259. package/dist/providers/pubmed/provider.js +224 -0
  260. package/dist/providers/pubmed/provider.js.map +1 -0
  261. package/dist/providers/pubmed/translator.d.ts +7 -0
  262. package/dist/providers/pubmed/translator.d.ts.map +1 -0
  263. package/dist/providers/pubmed/translator.js +143 -0
  264. package/dist/providers/pubmed/translator.js.map +1 -0
  265. package/dist/providers/pubmed/types.d.ts +72 -0
  266. package/dist/providers/pubmed/types.d.ts.map +1 -0
  267. package/dist/providers/scopus/client.d.ts +64 -0
  268. package/dist/providers/scopus/client.d.ts.map +1 -0
  269. package/dist/providers/scopus/client.js +155 -0
  270. package/dist/providers/scopus/client.js.map +1 -0
  271. package/dist/providers/scopus/index.d.ts +21 -0
  272. package/dist/providers/scopus/index.d.ts.map +1 -0
  273. package/dist/providers/scopus/parser.d.ts +11 -0
  274. package/dist/providers/scopus/parser.d.ts.map +1 -0
  275. package/dist/providers/scopus/parser.js +128 -0
  276. package/dist/providers/scopus/parser.js.map +1 -0
  277. package/dist/providers/scopus/provider.d.ts +39 -0
  278. package/dist/providers/scopus/provider.d.ts.map +1 -0
  279. package/dist/providers/scopus/provider.js +175 -0
  280. package/dist/providers/scopus/provider.js.map +1 -0
  281. package/dist/providers/scopus/translator.d.ts +7 -0
  282. package/dist/providers/scopus/translator.d.ts.map +1 -0
  283. package/dist/providers/scopus/translator.js +83 -0
  284. package/dist/providers/scopus/translator.js.map +1 -0
  285. package/dist/providers/scopus/types.d.ts +86 -0
  286. package/dist/providers/scopus/types.d.ts.map +1 -0
  287. package/dist/query/index.d.ts +12 -0
  288. package/dist/query/index.d.ts.map +1 -0
  289. package/dist/query/parser.d.ts +18 -0
  290. package/dist/query/parser.d.ts.map +1 -0
  291. package/dist/query/parser.js +16 -0
  292. package/dist/query/parser.js.map +1 -0
  293. package/dist/query/types.d.ts +85 -0
  294. package/dist/query/types.d.ts.map +1 -0
  295. package/dist/query/validator.d.ts +635 -0
  296. package/dist/query/validator.d.ts.map +1 -0
  297. package/dist/query/validator.js +117 -0
  298. package/dist/query/validator.js.map +1 -0
  299. package/dist/session/index.d.ts +14 -0
  300. package/dist/session/index.d.ts.map +1 -0
  301. package/dist/session/logger.d.ts +15 -0
  302. package/dist/session/logger.d.ts.map +1 -0
  303. package/dist/session/logger.js +18 -0
  304. package/dist/session/logger.js.map +1 -0
  305. package/dist/session/manager.d.ts +63 -0
  306. package/dist/session/manager.d.ts.map +1 -0
  307. package/dist/session/manager.js +193 -0
  308. package/dist/session/manager.js.map +1 -0
  309. package/dist/session/types.d.ts +182 -0
  310. package/dist/session/types.d.ts.map +1 -0
  311. package/dist/utils/deep-merge.d.ts +17 -0
  312. package/dist/utils/deep-merge.d.ts.map +1 -0
  313. package/dist/utils/deep-merge.js +23 -0
  314. package/dist/utils/deep-merge.js.map +1 -0
  315. package/dist/utils/path.d.ts +9 -0
  316. package/dist/utils/path.d.ts.map +1 -0
  317. package/dist/utils/path.js +15 -0
  318. package/dist/utils/path.js.map +1 -0
  319. package/package.json +82 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-executor.js","sources":["../../../src/cli/commands/search-executor.ts"],"sourcesContent":["/**\n * Search executor for CLI search command.\n *\n * Handles the actual execution of searches across multiple providers,\n * including session creation, progress display, and result storage.\n */\nimport { readFile, writeFile, appendFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport type { SearchCommandOptions } from './search.js';\nimport type { Config } from '../../config/index.js';\nimport type {\n Article,\n Provider,\n ProviderName,\n TranslatedQuery,\n} from '../../providers/base/types.js';\nimport type { QueryAST } from '../../query/types.js';\nimport { parseQueryString } from '../../query/index.js';\nimport {\n createSession,\n updateDatabaseStatus,\n updateSessionStatus,\n} from '../../session/manager.js';\nimport { MultiProviderProgress } from '../utils/progress.js';\nimport { PubMedProvider } from '../../providers/pubmed/provider.js';\nimport type { PubMedConfig } from '../../providers/pubmed/types.js';\nimport { ERICProvider } from '../../providers/eric/provider.js';\nimport { ArxivProvider } from '../../providers/arxiv/provider.js';\nimport { ScopusProvider } from '../../providers/scopus/provider.js';\nimport type { ScopusConfig } from '../../providers/scopus/types.js';\nimport { translateQuery as translatePubmed } from '../../providers/pubmed/translator.js';\nimport { translateQuery as translateEric } from '../../providers/eric/translator.js';\nimport { translateQuery as translateArxiv } from '../../providers/arxiv/translator.js';\nimport { translateQuery as translateScopus } from '../../providers/scopus/translator.js';\nimport { stringify as stringifyYaml } from 'yaml';\nimport { registerArticles, saveRegistrationRecord } from '../../integration/register.js';\nimport type { RegistrationRecord } from '../../integration/types.js';\nimport { checkRefAvailable } from '../../integration/ref-cli.js';\n\n/**\n * Result of a search execution.\n */\nexport interface SearchExecutionResult {\n success: boolean;\n sessionId?: string;\n results?: Record<string, { hits: number; retrieved: number }>;\n error?: string;\n autoRegisterResult?: RegistrationRecord;\n}\n\n/**\n * Available providers that are implemented.\n */\nconst IMPLEMENTED_PROVIDERS: ProviderName[] = ['pubmed', 'eric', 'arxiv', 'scopus'];\n\n/**\n * Create a provider instance for the given provider name.\n */\nexport function createProviderInstance(\n name: ProviderName,\n config: Config\n): Provider {\n const providerConfig = config.providers[name];\n\n switch (name) {\n case 'pubmed': {\n if (!providerConfig.email) {\n console.warn(\n 'Warning: No email configured for PubMed. Set providers.pubmed.email in config.'\n );\n }\n const pubmedOpts: PubMedConfig = {\n email: providerConfig.email ?? 'search-hub@example.com',\n rateLimit: providerConfig.rate_limit,\n timeout: providerConfig.timeout,\n retries: providerConfig.retries,\n };\n if (providerConfig.api_key) {\n pubmedOpts.apiKey = providerConfig.api_key;\n }\n return new PubMedProvider(pubmedOpts);\n }\n case 'eric':\n return new ERICProvider({\n rateLimit: providerConfig.rate_limit,\n timeout: providerConfig.timeout,\n retries: providerConfig.retries,\n });\n case 'arxiv':\n return new ArxivProvider({\n rateLimit: providerConfig.rate_limit,\n timeout: providerConfig.timeout,\n retries: providerConfig.retries,\n });\n case 'scopus': {\n const scopusOpts: ScopusConfig = {\n apiKey: providerConfig.api_key ?? '',\n rateLimit: providerConfig.rate_limit,\n timeout: providerConfig.timeout,\n retries: providerConfig.retries,\n };\n if (providerConfig.inst_token) {\n scopusOpts.instToken = providerConfig.inst_token;\n }\n return new ScopusProvider(scopusOpts);\n }\n default:\n throw new Error(`Provider '${name}' is not implemented`);\n }\n}\n\n/**\n * Translate a query AST for a specific provider.\n */\nfunction translateQueryForProvider(\n ast: QueryAST,\n provider: ProviderName\n): TranslatedQuery {\n switch (provider) {\n case 'pubmed':\n return translatePubmed(ast);\n case 'eric':\n return translateEric(ast);\n case 'arxiv':\n return translateArxiv(ast);\n case 'scopus':\n return translateScopus(ast);\n default:\n throw new Error(`No translator for provider '${provider}'`);\n }\n}\n\n/**\n * Get enabled providers from config, optionally filtered by user selection.\n */\nfunction getEnabledProviders(\n config: Config,\n requestedProviders?: ProviderName[]\n): ProviderName[] {\n const enabledInConfig = IMPLEMENTED_PROVIDERS.filter(\n (name) => config.providers[name].enabled\n );\n\n if (requestedProviders && requestedProviders.length > 0) {\n return requestedProviders.filter((p) => enabledInConfig.includes(p));\n }\n\n return enabledInConfig;\n}\n\n/**\n * Execute a search across multiple providers.\n */\nexport async function executeSearch(\n options: SearchCommandOptions,\n sessionsDir: string,\n config: Config,\n showProgress = true\n): Promise<SearchExecutionResult> {\n let ast: QueryAST | undefined;\n let queryContent: string;\n let queryFile: string;\n\n // Handle direct query mode\n if (options.directQuery && options.providers && options.providers.length === 1) {\n queryFile = 'direct-query';\n\n // For direct query, we create a minimal AST structure\n ast = {\n name: options.sessionName ?? 'direct-query',\n blocks: [\n {\n field: 'all',\n terms: { keywords: [options.directQuery] },\n operator: 'AND',\n },\n ],\n filters: {},\n overrides: {},\n };\n\n // Generate YAML safely using yaml library to handle special characters\n queryContent = stringifyYaml({\n name: ast.name,\n blocks: ast.blocks,\n filters: ast.filters,\n });\n } else if (options.queryFile) {\n // Parse query file\n try {\n queryContent = await readFile(options.queryFile, 'utf-8');\n ast = parseQueryString(queryContent);\n queryFile = options.queryFile;\n } catch (error) {\n return {\n success: false,\n error: `Failed to parse query file: ${error instanceof Error ? error.message : error}`,\n };\n }\n } else {\n return {\n success: false,\n error: 'Either queryFile or directQuery with provider is required',\n };\n }\n\n // Determine which providers to use\n const providers = getEnabledProviders(config, options.providers);\n\n if (providers.length === 0) {\n return {\n success: false,\n error: 'No providers enabled or selected',\n };\n }\n\n // Create query hash\n const queryHash = createHash('sha256').update(queryContent).digest('hex').slice(0, 8);\n\n // Create session\n let session;\n try {\n const sessionOpts: Parameters<typeof createSession>[0] = {\n name: options.sessionName ?? ast.name,\n queryFile,\n queryContent,\n queryHash,\n targets: providers,\n sessionsDir,\n };\n if (ast.description) {\n sessionOpts.description = ast.description;\n }\n session = await createSession(sessionOpts);\n } catch (error) {\n return {\n success: false,\n error: `Failed to create session: ${error instanceof Error ? error.message : error}`,\n };\n }\n\n const sessionId = session.id;\n const results: Record<string, { hits: number; retrieved: number }> = {};\n\n // Create progress display if enabled\n let progress: MultiProviderProgress | undefined;\n if (showProgress && process.stdout.isTTY) {\n progress = new MultiProviderProgress(providers);\n }\n\n // Execute search for each provider\n for (const providerName of providers) {\n try {\n // Create provider instance\n const provider = createProviderInstance(providerName, config);\n\n // Translate query\n let translatedQuery: TranslatedQuery;\n if (options.directQuery && options.providers?.length === 1) {\n // For direct query, use the native query string directly\n translatedQuery = {\n native: options.directQuery,\n provider: providerName,\n };\n } else {\n translatedQuery = translateQueryForProvider(ast, providerName);\n }\n\n // Write translated query to session\n const queryPath = join(sessionsDir, sessionId, `${providerName}_query.txt`);\n await writeFile(queryPath, translatedQuery.native, 'utf-8');\n\n // Update database status to in_progress\n await updateDatabaseStatus(\n sessionId,\n providerName,\n {\n status: 'in_progress',\n startedAt: new Date().toISOString(),\n },\n sessionsDir\n );\n\n // Prepare results file path\n const resultsPath = join(sessionsDir, sessionId, `${providerName}_results.jsonl`);\n\n // Execute search\n let retrievedCount = 0;\n let totalHits = 0;\n\n progress?.update(providerName, 0, 0, 'in_progress');\n\n const searchOptions = {\n maxResults: options.maxResults ?? config.providers[providerName].max_results,\n };\n\n for await (const article of provider.search(translatedQuery, searchOptions)) {\n retrievedCount++;\n\n // Write article to JSONL file\n await appendFile(resultsPath, JSON.stringify(article) + '\\n', 'utf-8');\n\n // Update progress (estimate total from first batch)\n if (totalHits === 0) {\n // Estimate total - this is provider-dependent, we'll use retrieved count as minimum\n totalHits = Math.max(retrievedCount * 10, 100);\n }\n progress?.update(providerName, retrievedCount, totalHits, 'in_progress');\n }\n\n // Update final totals\n totalHits = retrievedCount; // Use actual count as final total\n\n // Mark as completed\n progress?.complete(providerName);\n\n // Update database status\n await updateDatabaseStatus(\n sessionId,\n providerName,\n {\n status: 'completed',\n completedAt: new Date().toISOString(),\n totalHits,\n retrievedCount,\n files: {\n query: `${providerName}_query.txt`,\n results: `${providerName}_results.jsonl`,\n },\n },\n sessionsDir\n );\n\n results[providerName] = { hits: totalHits, retrieved: retrievedCount };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n progress?.fail(providerName, errorMessage);\n\n // Update database status with error\n await updateDatabaseStatus(\n sessionId,\n providerName,\n {\n status: 'failed',\n completedAt: new Date().toISOString(),\n error: {\n code: 'SEARCH_ERROR',\n message: errorMessage,\n retryable: true,\n },\n },\n sessionsDir\n );\n\n results[providerName] = { hits: 0, retrieved: 0 };\n }\n }\n\n // Stop progress display\n progress?.stop();\n\n // Determine overall session status\n const anyFailed = providers.some((p) => {\n const r = results[p];\n return r && r.retrieved === 0 && r.hits === 0;\n });\n const anySucceeded = providers.some((p) => {\n const r = results[p];\n return r && r.retrieved > 0;\n });\n\n let sessionStatus: 'completed' | 'partial' | 'failed';\n if (!anyFailed) {\n sessionStatus = 'completed';\n } else if (anySucceeded) {\n sessionStatus = 'partial';\n } else {\n sessionStatus = 'failed';\n }\n\n // Update session status\n await updateSessionStatus(sessionId, sessionStatus, sessionsDir);\n\n if (sessionStatus === 'failed') {\n return {\n success: false,\n sessionId,\n results,\n error: 'All providers failed',\n };\n }\n\n // Auto-register if enabled\n let autoRegisterResult: RegistrationRecord | undefined;\n if (\n config.integration.reference_manager.enabled &&\n config.integration.reference_manager.auto_register\n ) {\n const refAvailable = await checkRefAvailable();\n if (refAvailable) {\n // Load all articles from results files\n const allArticles = await loadArticlesFromSession(sessionsDir, sessionId, providers);\n\n if (allArticles.length > 0) {\n autoRegisterResult = await registerArticles(allArticles, {\n sessionId,\n sessionDir: join(sessionsDir, sessionId),\n withAbstracts: config.integration.reference_manager.with_abstracts,\n });\n\n // Save registration record\n await saveRegistrationRecord(join(sessionsDir, sessionId), autoRegisterResult);\n }\n }\n }\n\n const result: SearchExecutionResult = {\n success: true,\n sessionId,\n results,\n };\n\n if (autoRegisterResult) {\n result.autoRegisterResult = autoRegisterResult;\n }\n\n return result;\n}\n\n/**\n * Load all articles from a session's results files.\n */\nasync function loadArticlesFromSession(\n sessionsDir: string,\n sessionId: string,\n providers: ProviderName[]\n): Promise<Article[]> {\n const articles: Article[] = [];\n\n for (const provider of providers) {\n const resultsPath = join(sessionsDir, sessionId, `${provider}_results.jsonl`);\n try {\n const content = await readFile(resultsPath, 'utf-8');\n const lines = content.trim().split('\\n').filter((line) => line.length > 0);\n for (const line of lines) {\n try {\n const article = JSON.parse(line) as Article;\n articles.push(article);\n } catch {\n // Skip invalid JSON lines\n }\n }\n } catch {\n // Skip if file doesn't exist\n }\n }\n\n return articles;\n}\n"],"names":["translatePubmed","translateEric","translateArxiv","translateScopus","stringifyYaml"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { ProviderName } from '../../session/types.js';
2
+ export interface SearchCommandOptions {
3
+ queryFile?: string;
4
+ directQuery?: string;
5
+ providers?: ProviderName[];
6
+ sessionName?: string;
7
+ maxResults?: number;
8
+ dryRun?: boolean;
9
+ noResume?: boolean;
10
+ }
11
+ export interface CommandLineOptions {
12
+ db?: string | undefined;
13
+ query?: string | undefined;
14
+ name?: string | undefined;
15
+ maxResults?: string | undefined;
16
+ dryRun?: boolean | undefined;
17
+ noResume?: boolean | undefined;
18
+ }
19
+ export interface TranslationResult {
20
+ provider: string;
21
+ query: string;
22
+ }
23
+ export interface ValidationResult {
24
+ valid: boolean;
25
+ error?: string;
26
+ }
27
+ export declare function parseSearchOptions(queryFile: string | undefined, options: CommandLineOptions): SearchCommandOptions;
28
+ export declare function validateSearchInput(options: SearchCommandOptions): ValidationResult;
29
+ export declare function formatDryRunOutput(translations: TranslationResult[]): string;
30
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,EAAE,kBAAkB,GAC1B,oBAAoB,CAgCtB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,gBAAgB,CA0BnF;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAgB5E"}
@@ -0,0 +1,67 @@
1
+ import { parseProviderNames } from "../utils/validation.js";
2
+ function parseSearchOptions(queryFile, options) {
3
+ const result = {};
4
+ if (queryFile) {
5
+ result.queryFile = queryFile;
6
+ }
7
+ if (options.query) {
8
+ result.directQuery = options.query;
9
+ }
10
+ if (options.db) {
11
+ result.providers = parseProviderNames(options.db);
12
+ }
13
+ if (options.name) {
14
+ result.sessionName = options.name;
15
+ }
16
+ if (options.maxResults) {
17
+ result.maxResults = parseInt(options.maxResults, 10);
18
+ }
19
+ if (options.dryRun) {
20
+ result.dryRun = true;
21
+ }
22
+ if (options.noResume) {
23
+ result.noResume = true;
24
+ }
25
+ return result;
26
+ }
27
+ function validateSearchInput(options) {
28
+ if (!options.queryFile && !options.directQuery) {
29
+ return {
30
+ valid: false,
31
+ error: "Either a query file or --query option is required"
32
+ };
33
+ }
34
+ if (options.directQuery && (!options.providers || options.providers.length === 0)) {
35
+ return {
36
+ valid: false,
37
+ error: "Direct query (--query) requires --db option to specify the provider"
38
+ };
39
+ }
40
+ if (options.directQuery && options.providers && options.providers.length > 1) {
41
+ return {
42
+ valid: false,
43
+ error: "Direct query (--query) can only be used with a single provider (--db)"
44
+ };
45
+ }
46
+ return { valid: true };
47
+ }
48
+ function formatDryRunOutput(translations) {
49
+ if (translations.length === 0) {
50
+ return "No translations available.";
51
+ }
52
+ const lines = [];
53
+ lines.push("Translated queries:");
54
+ lines.push("");
55
+ for (const t of translations) {
56
+ lines.push(`[${t.provider}]`);
57
+ lines.push(t.query);
58
+ lines.push("");
59
+ }
60
+ return lines.join("\n");
61
+ }
62
+ export {
63
+ formatDryRunOutput,
64
+ parseSearchOptions,
65
+ validateSearchInput
66
+ };
67
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sources":["../../../src/cli/commands/search.ts"],"sourcesContent":["import type { ProviderName } from '../../session/types.js';\nimport { parseProviderNames } from '../utils/validation.js';\n\nexport interface SearchCommandOptions {\n queryFile?: string;\n directQuery?: string;\n providers?: ProviderName[];\n sessionName?: string;\n maxResults?: number;\n dryRun?: boolean;\n noResume?: boolean;\n}\n\nexport interface CommandLineOptions {\n db?: string | undefined;\n query?: string | undefined;\n name?: string | undefined;\n maxResults?: string | undefined;\n dryRun?: boolean | undefined;\n noResume?: boolean | undefined;\n}\n\nexport interface TranslationResult {\n provider: string;\n query: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n}\n\nexport function parseSearchOptions(\n queryFile: string | undefined,\n options: CommandLineOptions\n): SearchCommandOptions {\n const result: SearchCommandOptions = {};\n\n if (queryFile) {\n result.queryFile = queryFile;\n }\n\n if (options.query) {\n result.directQuery = options.query;\n }\n\n if (options.db) {\n result.providers = parseProviderNames(options.db);\n }\n\n if (options.name) {\n result.sessionName = options.name;\n }\n\n if (options.maxResults) {\n result.maxResults = parseInt(options.maxResults, 10);\n }\n\n if (options.dryRun) {\n result.dryRun = true;\n }\n\n if (options.noResume) {\n result.noResume = true;\n }\n\n return result;\n}\n\nexport function validateSearchInput(options: SearchCommandOptions): ValidationResult {\n // Case 1: Neither query file nor direct query\n if (!options.queryFile && !options.directQuery) {\n return {\n valid: false,\n error: 'Either a query file or --query option is required',\n };\n }\n\n // Case 2: Direct query without provider\n if (options.directQuery && (!options.providers || options.providers.length === 0)) {\n return {\n valid: false,\n error: 'Direct query (--query) requires --db option to specify the provider',\n };\n }\n\n // Case 3: Direct query with multiple providers\n if (options.directQuery && options.providers && options.providers.length > 1) {\n return {\n valid: false,\n error: 'Direct query (--query) can only be used with a single provider (--db)',\n };\n }\n\n return { valid: true };\n}\n\nexport function formatDryRunOutput(translations: TranslationResult[]): string {\n if (translations.length === 0) {\n return 'No translations available.';\n }\n\n const lines: string[] = [];\n lines.push('Translated queries:');\n lines.push('');\n\n for (const t of translations) {\n lines.push(`[${t.provider}]`);\n lines.push(t.query);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n"],"names":[],"mappings":";AAgCO,SAAS,mBACd,WACA,SACsB;AACtB,QAAM,SAA+B,CAAA;AAErC,MAAI,WAAW;AACb,WAAO,YAAY;AAAA,EACrB;AAEA,MAAI,QAAQ,OAAO;AACjB,WAAO,cAAc,QAAQ;AAAA,EAC/B;AAEA,MAAI,QAAQ,IAAI;AACd,WAAO,YAAY,mBAAmB,QAAQ,EAAE;AAAA,EAClD;AAEA,MAAI,QAAQ,MAAM;AAChB,WAAO,cAAc,QAAQ;AAAA,EAC/B;AAEA,MAAI,QAAQ,YAAY;AACtB,WAAO,aAAa,SAAS,QAAQ,YAAY,EAAE;AAAA,EACrD;AAEA,MAAI,QAAQ,QAAQ;AAClB,WAAO,SAAS;AAAA,EAClB;AAEA,MAAI,QAAQ,UAAU;AACpB,WAAO,WAAW;AAAA,EACpB;AAEA,SAAO;AACT;AAEO,SAAS,oBAAoB,SAAiD;AAEnF,MAAI,CAAC,QAAQ,aAAa,CAAC,QAAQ,aAAa;AAC9C,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IAAA;AAAA,EAEX;AAGA,MAAI,QAAQ,gBAAgB,CAAC,QAAQ,aAAa,QAAQ,UAAU,WAAW,IAAI;AACjF,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IAAA;AAAA,EAEX;AAGA,MAAI,QAAQ,eAAe,QAAQ,aAAa,QAAQ,UAAU,SAAS,GAAG;AAC5E,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IAAA;AAAA,EAEX;AAEA,SAAO,EAAE,OAAO,KAAA;AAClB;AAEO,SAAS,mBAAmB,cAA2C;AAC5E,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,QAAkB,CAAA;AACxB,QAAM,KAAK,qBAAqB;AAChC,QAAM,KAAK,EAAE;AAEb,aAAW,KAAK,cAAc;AAC5B,UAAM,KAAK,IAAI,EAAE,QAAQ,GAAG;AAC5B,UAAM,KAAK,EAAE,KAAK;AAClB,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;"}
@@ -0,0 +1,41 @@
1
+ export interface SessionListItem {
2
+ id: string;
3
+ name: string;
4
+ status: string;
5
+ createdAt: string;
6
+ progress: string;
7
+ }
8
+ export interface DatabaseDetails {
9
+ provider: string;
10
+ status: string;
11
+ totalHits: number;
12
+ retrievedCount: number;
13
+ error?: string;
14
+ }
15
+ export interface SessionDetails {
16
+ id: string;
17
+ name: string;
18
+ description?: string;
19
+ status: string;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ queryFile: string;
23
+ totalHits: number;
24
+ totalRetrieved: number;
25
+ databases: DatabaseDetails[];
26
+ }
27
+ export interface ListOptions {
28
+ all: boolean;
29
+ }
30
+ export interface FormatOptions {
31
+ json: boolean;
32
+ }
33
+ export declare function listSessionsForDisplay(sessionsDir: string, options: ListOptions): Promise<SessionListItem[]>;
34
+ export declare function getSessionDetails(sessionId: string, sessionsDir: string): Promise<{
35
+ success: boolean;
36
+ session?: SessionDetails;
37
+ error?: string;
38
+ }>;
39
+ export declare function formatSessionList(sessions: SessionListItem[], options: FormatOptions): string;
40
+ export declare function formatSessionDetails(details: SessionDetails, options: FormatOptions): string;
41
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,eAAe,EAAE,CAAC,CAc5B;AAED,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6CzE;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,eAAe,EAAE,EAC3B,OAAO,EAAE,aAAa,GACrB,MAAM,CAkBR;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,aAAa,GACrB,MAAM,CA+BR"}
@@ -0,0 +1,123 @@
1
+ import { loadSession, listSessions } from "../../session/manager.js";
2
+ async function listSessionsForDisplay(sessionsDir, options) {
3
+ const summaries = await listSessions(sessionsDir);
4
+ const filtered = options.all ? summaries : summaries.filter((s) => s.status !== "completed");
5
+ return filtered.map((s) => ({
6
+ id: s.id,
7
+ name: s.name,
8
+ status: s.status,
9
+ createdAt: s.createdAt,
10
+ progress: `${s.totalRetrieved}/${s.totalHits}`
11
+ }));
12
+ }
13
+ async function getSessionDetails(sessionId, sessionsDir) {
14
+ try {
15
+ const session = await loadSession(sessionId, sessionsDir);
16
+ const databases = [];
17
+ for (const [provider, dbStatus] of Object.entries(session.databases)) {
18
+ if (!dbStatus) continue;
19
+ const dbDetail = {
20
+ provider,
21
+ status: dbStatus.status,
22
+ totalHits: dbStatus.totalHits ?? 0,
23
+ retrievedCount: dbStatus.retrievedCount ?? 0
24
+ };
25
+ if (dbStatus.error?.message) {
26
+ dbDetail.error = dbStatus.error.message;
27
+ }
28
+ databases.push(dbDetail);
29
+ }
30
+ const sessionDetails = {
31
+ id: session.id,
32
+ name: session.name,
33
+ status: session.summary.status,
34
+ createdAt: session.createdAt,
35
+ updatedAt: session.updatedAt,
36
+ queryFile: session.query.file,
37
+ totalHits: session.summary.totalHits,
38
+ totalRetrieved: session.summary.totalRetrieved,
39
+ databases
40
+ };
41
+ if (session.description) {
42
+ sessionDetails.description = session.description;
43
+ }
44
+ return {
45
+ success: true,
46
+ session: sessionDetails
47
+ };
48
+ } catch (error) {
49
+ const message = error instanceof Error ? error.message : "Unknown error";
50
+ return {
51
+ success: false,
52
+ error: message
53
+ };
54
+ }
55
+ }
56
+ function formatSessionList(sessions, options) {
57
+ if (options.json) {
58
+ return JSON.stringify(sessions, null, 2);
59
+ }
60
+ if (sessions.length === 0) {
61
+ return "No sessions found.";
62
+ }
63
+ const header = `${"ID".padEnd(35)} ${"NAME".padEnd(20)} ${"STATUS".padEnd(15)} ${"PROGRESS".padEnd(12)} CREATED`;
64
+ const separator = "-".repeat(100);
65
+ const rows = sessions.map((s) => {
66
+ const date = new Date(s.createdAt).toLocaleDateString();
67
+ return `${s.id.padEnd(35)} ${s.name.padEnd(20)} ${s.status.padEnd(15)} ${s.progress.padEnd(12)} ${date}`;
68
+ });
69
+ return [header, separator, ...rows].join("\n");
70
+ }
71
+ function formatSessionDetails(details, options) {
72
+ if (options.json) {
73
+ return JSON.stringify(details, null, 2);
74
+ }
75
+ const lines = [];
76
+ lines.push(`Session: ${details.name}`);
77
+ lines.push(`ID: ${details.id}`);
78
+ if (details.description) {
79
+ lines.push(`Description: ${details.description}`);
80
+ }
81
+ lines.push(`Status: ${details.status}`);
82
+ lines.push(`Query File: ${details.queryFile}`);
83
+ lines.push(`Created: ${new Date(details.createdAt).toLocaleString()}`);
84
+ lines.push(`Updated: ${new Date(details.updatedAt).toLocaleString()}`);
85
+ lines.push("");
86
+ lines.push(`Total: ${details.totalRetrieved}/${details.totalHits} results`);
87
+ lines.push("");
88
+ lines.push("Databases:");
89
+ for (const db of details.databases) {
90
+ const statusIcon = getStatusIcon(db.status);
91
+ let line = ` ${statusIcon} ${db.provider.padEnd(10)} ${db.status.padEnd(12)} ${db.retrievedCount}/${db.totalHits}`;
92
+ if (db.error) {
93
+ line += ` (${db.error})`;
94
+ }
95
+ lines.push(line);
96
+ }
97
+ return lines.join("\n");
98
+ }
99
+ function getStatusIcon(status) {
100
+ switch (status) {
101
+ case "completed":
102
+ return "✓";
103
+ // ✓
104
+ case "failed":
105
+ return "✗";
106
+ // ✗
107
+ case "in_progress":
108
+ return "⠋";
109
+ // ⠋
110
+ case "pending":
111
+ return "◼";
112
+ // ◼
113
+ default:
114
+ return " ";
115
+ }
116
+ }
117
+ export {
118
+ formatSessionDetails,
119
+ formatSessionList,
120
+ getSessionDetails,
121
+ listSessionsForDisplay
122
+ };
123
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sources":["../../../src/cli/commands/status.ts"],"sourcesContent":["import { listSessions, loadSession } from '../../session/manager.js';\n\nexport interface SessionListItem {\n id: string;\n name: string;\n status: string;\n createdAt: string;\n progress: string;\n}\n\nexport interface DatabaseDetails {\n provider: string;\n status: string;\n totalHits: number;\n retrievedCount: number;\n error?: string;\n}\n\nexport interface SessionDetails {\n id: string;\n name: string;\n description?: string;\n status: string;\n createdAt: string;\n updatedAt: string;\n queryFile: string;\n totalHits: number;\n totalRetrieved: number;\n databases: DatabaseDetails[];\n}\n\nexport interface ListOptions {\n all: boolean;\n}\n\nexport interface FormatOptions {\n json: boolean;\n}\n\nexport async function listSessionsForDisplay(\n sessionsDir: string,\n options: ListOptions\n): Promise<SessionListItem[]> {\n const summaries = await listSessions(sessionsDir);\n\n const filtered = options.all\n ? summaries\n : summaries.filter((s) => s.status !== 'completed');\n\n return filtered.map((s) => ({\n id: s.id,\n name: s.name,\n status: s.status,\n createdAt: s.createdAt,\n progress: `${s.totalRetrieved}/${s.totalHits}`,\n }));\n}\n\nexport async function getSessionDetails(\n sessionId: string,\n sessionsDir: string\n): Promise<{ success: boolean; session?: SessionDetails; error?: string }> {\n try {\n const session = await loadSession(sessionId, sessionsDir);\n\n const databases: DatabaseDetails[] = [];\n for (const [provider, dbStatus] of Object.entries(session.databases)) {\n if (!dbStatus) continue;\n const dbDetail: DatabaseDetails = {\n provider,\n status: dbStatus.status,\n totalHits: dbStatus.totalHits ?? 0,\n retrievedCount: dbStatus.retrievedCount ?? 0,\n };\n if (dbStatus.error?.message) {\n dbDetail.error = dbStatus.error.message;\n }\n databases.push(dbDetail);\n }\n\n const sessionDetails: SessionDetails = {\n id: session.id,\n name: session.name,\n status: session.summary.status,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt,\n queryFile: session.query.file,\n totalHits: session.summary.totalHits,\n totalRetrieved: session.summary.totalRetrieved,\n databases,\n };\n if (session.description) {\n sessionDetails.description = session.description;\n }\n\n return {\n success: true,\n session: sessionDetails,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n error: message,\n };\n }\n}\n\nexport function formatSessionList(\n sessions: SessionListItem[],\n options: FormatOptions\n): string {\n if (options.json) {\n return JSON.stringify(sessions, null, 2);\n }\n\n if (sessions.length === 0) {\n return 'No sessions found.';\n }\n\n const header = `${'ID'.padEnd(35)} ${'NAME'.padEnd(20)} ${'STATUS'.padEnd(15)} ${'PROGRESS'.padEnd(12)} CREATED`;\n const separator = '-'.repeat(100);\n\n const rows = sessions.map((s) => {\n const date = new Date(s.createdAt).toLocaleDateString();\n return `${s.id.padEnd(35)} ${s.name.padEnd(20)} ${s.status.padEnd(15)} ${s.progress.padEnd(12)} ${date}`;\n });\n\n return [header, separator, ...rows].join('\\n');\n}\n\nexport function formatSessionDetails(\n details: SessionDetails,\n options: FormatOptions\n): string {\n if (options.json) {\n return JSON.stringify(details, null, 2);\n }\n\n const lines: string[] = [];\n\n lines.push(`Session: ${details.name}`);\n lines.push(`ID: ${details.id}`);\n if (details.description) {\n lines.push(`Description: ${details.description}`);\n }\n lines.push(`Status: ${details.status}`);\n lines.push(`Query File: ${details.queryFile}`);\n lines.push(`Created: ${new Date(details.createdAt).toLocaleString()}`);\n lines.push(`Updated: ${new Date(details.updatedAt).toLocaleString()}`);\n lines.push('');\n lines.push(`Total: ${details.totalRetrieved}/${details.totalHits} results`);\n lines.push('');\n lines.push('Databases:');\n\n for (const db of details.databases) {\n const statusIcon = getStatusIcon(db.status);\n let line = ` ${statusIcon} ${db.provider.padEnd(10)} ${db.status.padEnd(12)} ${db.retrievedCount}/${db.totalHits}`;\n if (db.error) {\n line += ` (${db.error})`;\n }\n lines.push(line);\n }\n\n return lines.join('\\n');\n}\n\nfunction getStatusIcon(status: string): string {\n switch (status) {\n case 'completed':\n return '\\u2713'; // ✓\n case 'failed':\n return '\\u2717'; // ✗\n case 'in_progress':\n return '\\u280B'; // ⠋\n case 'pending':\n return '\\u25FC'; // ◼\n default:\n return ' ';\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ import { QueryAST } from '../query/types.js';
2
+ import { ProviderConfig } from '../config/schema.js';
3
+ /**
4
+ * Partial provider configuration for testing.
5
+ * All fields are optional to allow minimal test configs.
6
+ */
7
+ export type PartialProviderConfig = Partial<ProviderConfig>;
8
+ /**
9
+ * Partial config type for creating test configurations.
10
+ * All fields are optional to allow minimal test configs.
11
+ */
12
+ export interface PartialConfig {
13
+ session?: {
14
+ directory?: string;
15
+ };
16
+ log?: {
17
+ level?: 'debug' | 'info' | 'warn' | 'error';
18
+ };
19
+ output?: {
20
+ color?: boolean;
21
+ progress_bar?: boolean;
22
+ };
23
+ providers?: Partial<Record<string, PartialProviderConfig>>;
24
+ integration?: {
25
+ reference_manager?: {
26
+ enabled?: boolean;
27
+ command?: string;
28
+ auto_register?: boolean;
29
+ with_abstracts?: boolean;
30
+ };
31
+ };
32
+ }
33
+ /**
34
+ * Result of CLI execution
35
+ */
36
+ export interface ExecResult {
37
+ stdout: string;
38
+ stderr: string;
39
+ exitCode: number;
40
+ }
41
+ /**
42
+ * Options for CLI execution
43
+ */
44
+ export interface ExecOptions {
45
+ /** Environment variables to set */
46
+ env?: Record<string, string>;
47
+ /** Working directory */
48
+ cwd?: string;
49
+ /** Timeout in milliseconds (default: 30000) */
50
+ timeout?: number;
51
+ /** Input to pass to stdin */
52
+ input?: string;
53
+ }
54
+ /**
55
+ * E2E test context containing temp directories and cleanup
56
+ */
57
+ export interface E2EContext {
58
+ /** Root temp directory for this test */
59
+ tempDir: string;
60
+ /** Sessions directory */
61
+ sessionsDir: string;
62
+ /** Path to config file */
63
+ configPath: string;
64
+ /** Clean up all test artifacts */
65
+ cleanup: () => Promise<void>;
66
+ }
67
+ /**
68
+ * Create a temporary directory for E2E tests.
69
+ * Returns a unique directory path that can be cleaned up later.
70
+ */
71
+ export declare function createTempDir(): Promise<string>;
72
+ /**
73
+ * Set up a complete E2E test context with temp dirs and config.
74
+ * Call cleanup() after tests to remove all artifacts.
75
+ */
76
+ export declare function setupE2EContext(): Promise<E2EContext>;
77
+ /**
78
+ * Execute CLI command as a subprocess.
79
+ * Returns stdout, stderr, and exit code.
80
+ */
81
+ export declare function execCli(args: string[], options?: ExecOptions): Promise<ExecResult>;
82
+ /**
83
+ * Create a query YAML file from a QueryAST object.
84
+ * Returns the path to the created file.
85
+ */
86
+ export declare function createQueryFile(tempDir: string, query: QueryAST, filename?: string): Promise<string>;
87
+ /**
88
+ * Create a raw YAML query file from string content.
89
+ * Useful for testing invalid queries.
90
+ */
91
+ export declare function createRawQueryFile(tempDir: string, content: string, filename?: string): Promise<string>;
92
+ /**
93
+ * Create a config TOML file.
94
+ * Returns the path to the created file.
95
+ */
96
+ export declare function createConfig(tempDir: string, config: PartialConfig, filename?: string): Promise<string>;
97
+ /**
98
+ * Create a raw TOML config file from string content.
99
+ * Useful for testing invalid configs.
100
+ */
101
+ export declare function createRawConfig(tempDir: string, content: string, filename?: string): Promise<string>;
102
+ /**
103
+ * Create a simple test query for use in E2E tests.
104
+ * This is a minimal valid query that can be used across all providers.
105
+ */
106
+ export declare function createSimpleQuery(name?: string): QueryAST;
107
+ /**
108
+ * Sample query fixtures for different test scenarios
109
+ */
110
+ export declare const queryFixtures: {
111
+ /** Simple single-block query */
112
+ simple: QueryAST;
113
+ /** Multi-block query with filters */
114
+ multiBlock: {
115
+ name: string;
116
+ description: string;
117
+ blocks: ({
118
+ field: "title_abstract";
119
+ terms: {
120
+ keywords: string[];
121
+ };
122
+ operator: "AND";
123
+ } | {
124
+ field: "keyword";
125
+ terms: {
126
+ keywords: string[];
127
+ };
128
+ operator: "OR";
129
+ })[];
130
+ filters: {
131
+ yearFrom: number;
132
+ yearTo: number;
133
+ languages: string[];
134
+ };
135
+ overrides: {};
136
+ };
137
+ /** Query with MeSH terms (PubMed-specific) */
138
+ withMesh: {
139
+ name: string;
140
+ blocks: {
141
+ field: "title_abstract";
142
+ terms: {
143
+ keywords: string[];
144
+ mesh: string[];
145
+ };
146
+ operator: "AND";
147
+ }[];
148
+ filters: {};
149
+ overrides: {};
150
+ };
151
+ };
152
+ /**
153
+ * Invalid query fixtures for error testing
154
+ */
155
+ export declare const invalidQueryFixtures: {
156
+ /** Missing required name field */
157
+ missingName: string;
158
+ /** Invalid field type */
159
+ invalidField: string;
160
+ /** Empty keywords */
161
+ emptyKeywords: string;
162
+ /** Malformed YAML */
163
+ malformedYaml: string;
164
+ };
165
+ //# sourceMappingURL=e2e-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e2e-helpers.d.ts","sourceRoot":"","sources":["../../src/cli/e2e-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * CLI Exit Codes
3
+ *
4
+ * These codes indicate the type of error that occurred.
5
+ */
6
+ export declare const EXIT_CODES: {
7
+ /** Operation completed successfully */
8
+ readonly SUCCESS: 0;
9
+ /** General/unexpected error */
10
+ readonly GENERAL_ERROR: 1;
11
+ /** Configuration error (missing config, invalid config, etc.) */
12
+ readonly CONFIG_ERROR: 2;
13
+ /** Query validation error (invalid YAML, invalid query syntax) */
14
+ readonly QUERY_ERROR: 3;
15
+ /** Network/API error (connection failure, API rate limit, etc.) */
16
+ readonly NETWORK_ERROR: 4;
17
+ /** Session error (session not found, invalid session state, etc.) */
18
+ readonly SESSION_ERROR: 5;
19
+ };
20
+ export type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];
21
+ /**
22
+ * Exit code descriptions for help output.
23
+ */
24
+ export declare const EXIT_CODE_DESCRIPTIONS: Record<ExitCode, string>;
25
+ //# sourceMappingURL=exit-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../../src/cli/exit-codes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,UAAU;IACrB,uCAAuC;;IAEvC,+BAA+B;;IAE/B,iEAAiE;;IAEjE,kEAAkE;;IAElE,mEAAmE;;IAEnE,qEAAqE;;CAE7D,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAO3D,CAAC"}
@@ -0,0 +1,18 @@
1
+ const EXIT_CODES = {
2
+ /** Operation completed successfully */
3
+ SUCCESS: 0,
4
+ /** General/unexpected error */
5
+ GENERAL_ERROR: 1,
6
+ /** Configuration error (missing config, invalid config, etc.) */
7
+ CONFIG_ERROR: 2,
8
+ /** Query validation error (invalid YAML, invalid query syntax) */
9
+ QUERY_ERROR: 3,
10
+ /** Network/API error (connection failure, API rate limit, etc.) */
11
+ NETWORK_ERROR: 4,
12
+ /** Session error (session not found, invalid session state, etc.) */
13
+ SESSION_ERROR: 5
14
+ };
15
+ export {
16
+ EXIT_CODES
17
+ };
18
+ //# sourceMappingURL=exit-codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.js","sources":["../../src/cli/exit-codes.ts"],"sourcesContent":["/**\n * CLI Exit Codes\n *\n * These codes indicate the type of error that occurred.\n */\nexport const EXIT_CODES = {\n /** Operation completed successfully */\n SUCCESS: 0,\n /** General/unexpected error */\n GENERAL_ERROR: 1,\n /** Configuration error (missing config, invalid config, etc.) */\n CONFIG_ERROR: 2,\n /** Query validation error (invalid YAML, invalid query syntax) */\n QUERY_ERROR: 3,\n /** Network/API error (connection failure, API rate limit, etc.) */\n NETWORK_ERROR: 4,\n /** Session error (session not found, invalid session state, etc.) */\n SESSION_ERROR: 5,\n} as const;\n\nexport type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];\n\n/**\n * Exit code descriptions for help output.\n */\nexport const EXIT_CODE_DESCRIPTIONS: Record<ExitCode, string> = {\n [EXIT_CODES.SUCCESS]: 'Success',\n [EXIT_CODES.GENERAL_ERROR]: 'General error',\n [EXIT_CODES.CONFIG_ERROR]: 'Configuration error',\n [EXIT_CODES.QUERY_ERROR]: 'Query validation error',\n [EXIT_CODES.NETWORK_ERROR]: 'Network/API error',\n [EXIT_CODES.SESSION_ERROR]: 'Session error',\n};\n"],"names":[],"mappings":"AAKO,MAAM,aAAa;AAAA;AAAA,EAExB,SAAS;AAAA;AAAA,EAET,eAAe;AAAA;AAAA,EAEf,cAAc;AAAA;AAAA,EAEd,aAAa;AAAA;AAAA,EAEb,eAAe;AAAA;AAAA,EAEf,eAAe;AACjB;"}
@@ -0,0 +1,25 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Global CLI options available to all commands.
4
+ */
5
+ export interface GlobalOptions {
6
+ /** Path to config file */
7
+ config?: string;
8
+ /** Path to session directory */
9
+ sessionDir?: string;
10
+ /** Enable verbose output */
11
+ verbose: boolean;
12
+ /** Suppress all output except errors */
13
+ quiet: boolean;
14
+ /** Enable color output (default: true, use --no-color to disable) */
15
+ color: boolean;
16
+ }
17
+ /**
18
+ * Create and configure the CLI program.
19
+ */
20
+ export declare function createProgram(): Command;
21
+ /**
22
+ * Main entry point for CLI execution.
23
+ */
24
+ export declare function main(): Promise<void>;
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0DpC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IACf,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAwyBvC;AAED;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1C"}