@pharmatools/pubcrawl 2.0.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.
- package/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cache.d.ts +19 -0
- package/dist/lib/cache.d.ts.map +1 -0
- package/dist/lib/cache.js +52 -0
- package/dist/lib/cache.js.map +1 -0
- package/dist/lib/dailymed.d.ts +9 -0
- package/dist/lib/dailymed.d.ts.map +1 -0
- package/dist/lib/dailymed.js +58 -0
- package/dist/lib/dailymed.js.map +1 -0
- package/dist/lib/emc.d.ts +13 -0
- package/dist/lib/emc.d.ts.map +1 -0
- package/dist/lib/emc.js +215 -0
- package/dist/lib/emc.js.map +1 -0
- package/dist/lib/label-mapping.d.ts +8 -0
- package/dist/lib/label-mapping.d.ts.map +1 -0
- package/dist/lib/label-mapping.js +23 -0
- package/dist/lib/label-mapping.js.map +1 -0
- package/dist/lib/ncbi.d.ts +37 -0
- package/dist/lib/ncbi.d.ts.map +1 -0
- package/dist/lib/ncbi.js +175 -0
- package/dist/lib/ncbi.js.map +1 -0
- package/dist/lib/openfda.d.ts +8 -0
- package/dist/lib/openfda.d.ts.map +1 -0
- package/dist/lib/openfda.js +83 -0
- package/dist/lib/openfda.js.map +1 -0
- package/dist/lib/xml-parser.d.ts +23 -0
- package/dist/lib/xml-parser.d.ts.map +1 -0
- package/dist/lib/xml-parser.js +273 -0
- package/dist/lib/xml-parser.js.map +1 -0
- package/dist/tools/abstract.d.ts +3 -0
- package/dist/tools/abstract.d.ts.map +1 -0
- package/dist/tools/abstract.js +107 -0
- package/dist/tools/abstract.js.map +1 -0
- package/dist/tools/cite.d.ts +3 -0
- package/dist/tools/cite.d.ts.map +1 -0
- package/dist/tools/cite.js +188 -0
- package/dist/tools/cite.js.map +1 -0
- package/dist/tools/compare-labels.d.ts +3 -0
- package/dist/tools/compare-labels.d.ts.map +1 -0
- package/dist/tools/compare-labels.js +126 -0
- package/dist/tools/compare-labels.js.map +1 -0
- package/dist/tools/fulltext.d.ts +3 -0
- package/dist/tools/fulltext.d.ts.map +1 -0
- package/dist/tools/fulltext.js +88 -0
- package/dist/tools/fulltext.js.map +1 -0
- package/dist/tools/related.d.ts +3 -0
- package/dist/tools/related.d.ts.map +1 -0
- package/dist/tools/related.js +63 -0
- package/dist/tools/related.js.map +1 -0
- package/dist/tools/search-indication.d.ts +3 -0
- package/dist/tools/search-indication.d.ts.map +1 -0
- package/dist/tools/search-indication.js +73 -0
- package/dist/tools/search-indication.js.map +1 -0
- package/dist/tools/search.d.ts +3 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +69 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/smpc.d.ts +3 -0
- package/dist/tools/smpc.d.ts.map +1 -0
- package/dist/tools/smpc.js +52 -0
- package/dist/tools/smpc.js.map +1 -0
- package/dist/tools/trending.d.ts +3 -0
- package/dist/tools/trending.d.ts.map +1 -0
- package/dist/tools/trending.js +106 -0
- package/dist/tools/trending.js.map +1 -0
- package/dist/tools/uspi.d.ts +3 -0
- package/dist/tools/uspi.d.ts.map +1 -0
- package/dist/tools/uspi.js +117 -0
- package/dist/tools/uspi.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
- package/server.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PharmaTools.AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# PubCrawl
|
|
2
|
+
|
|
3
|
+
An [MCP server](https://modelcontextprotocol.io) that gives LLM clients access to PubMed, FDA drug labelling, and UK medicines data. A peer-reviewed pub crawl through the literature — and the label.
|
|
4
|
+
|
|
5
|
+
Built by [PharmaTools.AI](https://pharmatools.ai).
|
|
6
|
+
|
|
7
|
+
## Tools
|
|
8
|
+
|
|
9
|
+
### Literature
|
|
10
|
+
|
|
11
|
+
| Tool | What it does |
|
|
12
|
+
|------|-------------|
|
|
13
|
+
| `search_pubmed` | Search PubMed with filters for date range, article type, and sort order. Returns PMIDs, titles, authors, journals, and DOIs. |
|
|
14
|
+
| `get_abstract` | Get the full structured abstract for an article — broken into labeled sections (background, methods, results, conclusions) with keywords and MeSH terms. |
|
|
15
|
+
| `get_full_text` | Retrieve the full text of open-access articles from PubMed Central, with parsed sections, figure/table captions, and reference counts. |
|
|
16
|
+
| `find_related` | Find similar articles using PubMed's neighbor algorithm, ranked by relevance score. |
|
|
17
|
+
| `format_citation` | Generate a formatted citation in APA, Vancouver, Harvard, or BibTeX style. |
|
|
18
|
+
| `trending_papers` | Find recent papers on a topic, with optional filtering to high-impact journals (Nature, Science, Cell, NEJM, Lancet, JAMA, etc.). |
|
|
19
|
+
|
|
20
|
+
### Drug Labelling
|
|
21
|
+
|
|
22
|
+
| Tool | What it does |
|
|
23
|
+
|------|-------------|
|
|
24
|
+
| `get_uspi` | Pull US Prescribing Information sections from DailyMed — indications, dosing, warnings, contraindications, and more. Parsed from FDA structured product labels. |
|
|
25
|
+
| `get_smpc` | Retrieve UK Summary of Product Characteristics from the eMC — the UK equivalent of US prescribing information, with numbered SmPC sections. |
|
|
26
|
+
| `compare_labels` | Side-by-side comparison of US (USPI) and UK (SmPC) labelling for the same drug. Spot regulatory differences in indications, warnings, and dosing. |
|
|
27
|
+
| `search_by_indication` | Find drugs approved for a medical condition. Searches FDA labelling via OpenFDA, then cross-references UK availability on the eMC. |
|
|
28
|
+
|
|
29
|
+
## Setup
|
|
30
|
+
|
|
31
|
+
### Prerequisites
|
|
32
|
+
|
|
33
|
+
- Node.js 18+
|
|
34
|
+
- An MCP-compatible client (Claude Desktop, Cursor, etc.)
|
|
35
|
+
|
|
36
|
+
### Install and build
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
git clone https://github.com/nickjlamb/pubcrawl.git
|
|
40
|
+
cd pubcrawl
|
|
41
|
+
npm install
|
|
42
|
+
npm run build
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Configure Claude Desktop
|
|
46
|
+
|
|
47
|
+
Add to your `claude_desktop_config.json`:
|
|
48
|
+
|
|
49
|
+
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
50
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"mcpServers": {
|
|
55
|
+
"pubcrawl": {
|
|
56
|
+
"command": "node",
|
|
57
|
+
"args": ["/path/to/pubcrawl/dist/index.js"]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Restart Claude Desktop. PubCrawl will appear under **+ → Connectors**.
|
|
64
|
+
|
|
65
|
+
### NCBI API key (optional)
|
|
66
|
+
|
|
67
|
+
Without an API key, requests are rate-limited to 3/second. With one, you get 10/second.
|
|
68
|
+
|
|
69
|
+
1. Create a free NCBI account at https://www.ncbi.nlm.nih.gov/account/
|
|
70
|
+
2. Go to Account Settings → API Key Management
|
|
71
|
+
3. Add the key to your config:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"pubcrawl": {
|
|
77
|
+
"command": "node",
|
|
78
|
+
"args": ["/path/to/pubcrawl/dist/index.js"],
|
|
79
|
+
"env": {
|
|
80
|
+
"NCBI_API_KEY": "your_key_here"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Example prompts
|
|
88
|
+
|
|
89
|
+
Once connected, just ask naturally:
|
|
90
|
+
|
|
91
|
+
- "Search PubMed for recent clinical trials on semaglutide"
|
|
92
|
+
- "Get the abstract for PMID 38127654"
|
|
93
|
+
- "Find papers related to this one and format citations in APA"
|
|
94
|
+
- "What are the trending papers on CRISPR gene therapy this month?"
|
|
95
|
+
- "Get the full text of that paper from PMC"
|
|
96
|
+
- "Get the FDA prescribing information for metformin — just the indications and warnings"
|
|
97
|
+
- "Pull the UK SmPC for atorvastatin"
|
|
98
|
+
- "Compare US and UK labelling for lisinopril"
|
|
99
|
+
- "What drugs are approved for type 2 diabetes?"
|
|
100
|
+
|
|
101
|
+
## Development
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm run dev # TypeScript watch mode
|
|
105
|
+
npm run build # Compile to dist/
|
|
106
|
+
npm start # Run the server
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { setApiKey } from "./lib/ncbi.js";
|
|
6
|
+
import { registerSearchTool } from "./tools/search.js";
|
|
7
|
+
import { registerAbstractTool } from "./tools/abstract.js";
|
|
8
|
+
import { registerFullTextTool } from "./tools/fulltext.js";
|
|
9
|
+
import { registerRelatedTool } from "./tools/related.js";
|
|
10
|
+
import { registerCiteTool } from "./tools/cite.js";
|
|
11
|
+
import { registerTrendingTool } from "./tools/trending.js";
|
|
12
|
+
import { registerUspiTool } from "./tools/uspi.js";
|
|
13
|
+
import { registerSmpcTool } from "./tools/smpc.js";
|
|
14
|
+
import { registerCompareLabelsTool } from "./tools/compare-labels.js";
|
|
15
|
+
import { registerSearchIndicationTool } from "./tools/search-indication.js";
|
|
16
|
+
const server = new McpServer({
|
|
17
|
+
name: "pubcrawl",
|
|
18
|
+
version: "2.0.0",
|
|
19
|
+
});
|
|
20
|
+
// Configure NCBI API key if available (10 req/s vs 3 req/s)
|
|
21
|
+
if (process.env.NCBI_API_KEY) {
|
|
22
|
+
setApiKey(process.env.NCBI_API_KEY);
|
|
23
|
+
}
|
|
24
|
+
// Register all tools
|
|
25
|
+
registerSearchTool(server);
|
|
26
|
+
registerAbstractTool(server);
|
|
27
|
+
registerFullTextTool(server);
|
|
28
|
+
registerRelatedTool(server);
|
|
29
|
+
registerCiteTool(server);
|
|
30
|
+
registerTrendingTool(server);
|
|
31
|
+
registerUspiTool(server);
|
|
32
|
+
registerSmpcTool(server);
|
|
33
|
+
registerCompareLabelsTool(server);
|
|
34
|
+
registerSearchIndicationTool(server);
|
|
35
|
+
// Start server
|
|
36
|
+
async function main() {
|
|
37
|
+
const transport = new StdioServerTransport();
|
|
38
|
+
await server.connect(transport);
|
|
39
|
+
console.error("PubCrawl MCP server running on stdio");
|
|
40
|
+
}
|
|
41
|
+
main().catch((error) => {
|
|
42
|
+
console.error("Fatal error:", error);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAE5E,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,4DAA4D;AAC5D,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC7B,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AACtC,CAAC;AAED,qBAAqB;AACrB,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAC3B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAClC,4BAA4B,CAAC,MAAM,CAAC,CAAC;AAErC,eAAe;AACf,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;AACxD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const TTL: {
|
|
2
|
+
readonly SEARCH: number;
|
|
3
|
+
readonly ABSTRACT: number;
|
|
4
|
+
readonly FULLTEXT: number;
|
|
5
|
+
readonly RELATED: number;
|
|
6
|
+
readonly SUMMARY: number;
|
|
7
|
+
readonly LABEL: number;
|
|
8
|
+
};
|
|
9
|
+
export declare class LRUCache {
|
|
10
|
+
private cache;
|
|
11
|
+
private maxEntries;
|
|
12
|
+
constructor(maxEntries?: number);
|
|
13
|
+
get<T>(key: string): T | undefined;
|
|
14
|
+
set<T>(key: string, value: T, ttl: number): void;
|
|
15
|
+
clear(): void;
|
|
16
|
+
get size(): number;
|
|
17
|
+
}
|
|
18
|
+
export declare const cache: LRUCache;
|
|
19
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,GAAG;;;;;;;CAON,CAAC;AAEX,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,SAAsB;IAI5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAelC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAgBhD,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED,eAAO,MAAM,KAAK,UAAiB,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const DEFAULT_MAX_ENTRIES = 500;
|
|
2
|
+
const ONE_HOUR_MS = 60 * 60 * 1000;
|
|
3
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
4
|
+
export const TTL = {
|
|
5
|
+
SEARCH: ONE_HOUR_MS,
|
|
6
|
+
ABSTRACT: ONE_DAY_MS,
|
|
7
|
+
FULLTEXT: ONE_DAY_MS,
|
|
8
|
+
RELATED: ONE_HOUR_MS,
|
|
9
|
+
SUMMARY: ONE_HOUR_MS,
|
|
10
|
+
LABEL: ONE_DAY_MS,
|
|
11
|
+
};
|
|
12
|
+
export class LRUCache {
|
|
13
|
+
cache = new Map();
|
|
14
|
+
maxEntries;
|
|
15
|
+
constructor(maxEntries = DEFAULT_MAX_ENTRIES) {
|
|
16
|
+
this.maxEntries = maxEntries;
|
|
17
|
+
}
|
|
18
|
+
get(key) {
|
|
19
|
+
const entry = this.cache.get(key);
|
|
20
|
+
if (!entry)
|
|
21
|
+
return undefined;
|
|
22
|
+
if (Date.now() - entry.timestamp > entry.ttl) {
|
|
23
|
+
this.cache.delete(key);
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
// Move to end (most recently used)
|
|
27
|
+
this.cache.delete(key);
|
|
28
|
+
this.cache.set(key, entry);
|
|
29
|
+
return entry.value;
|
|
30
|
+
}
|
|
31
|
+
set(key, value, ttl) {
|
|
32
|
+
if (this.cache.has(key)) {
|
|
33
|
+
this.cache.delete(key);
|
|
34
|
+
}
|
|
35
|
+
if (this.cache.size >= this.maxEntries) {
|
|
36
|
+
// Evict least recently used (first entry)
|
|
37
|
+
const firstKey = this.cache.keys().next().value;
|
|
38
|
+
if (firstKey !== undefined) {
|
|
39
|
+
this.cache.delete(firstKey);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
this.cache.set(key, { value, timestamp: Date.now(), ttl });
|
|
43
|
+
}
|
|
44
|
+
clear() {
|
|
45
|
+
this.cache.clear();
|
|
46
|
+
}
|
|
47
|
+
get size() {
|
|
48
|
+
return this.cache.size;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export const cache = new LRUCache();
|
|
52
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"AAEA,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACnC,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEvC,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,MAAM,EAAE,WAAW;IACnB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,WAAW;IACpB,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,UAAU;CACT,CAAC;AAEX,MAAM,OAAO,QAAQ;IACX,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;IAC/C,UAAU,CAAS;IAE3B,YAAY,UAAU,GAAG,mBAAmB;QAC1C,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,GAAG,CAAI,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAE7B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,mCAAmC;QACnC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC3B,OAAO,KAAK,CAAC,KAAU,CAAC;IAC1B,CAAC;IAED,GAAG,CAAI,GAAW,EAAE,KAAQ,EAAE,GAAW;QACvC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACvC,0CAA0C;YAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAChD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface DailyMedSearchResult {
|
|
2
|
+
setid: string;
|
|
3
|
+
title: string;
|
|
4
|
+
published_date: string;
|
|
5
|
+
spl_version: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function searchDrugLabels(drugName: string): Promise<DailyMedSearchResult[]>;
|
|
8
|
+
export declare function fetchSplXml(setid: string): Promise<string>;
|
|
9
|
+
//# sourceMappingURL=dailymed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dailymed.d.ts","sourceRoot":"","sources":["../../src/lib/dailymed.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAyBxF;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWhE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { cache, TTL } from "./cache.js";
|
|
2
|
+
const BASE_URL = "https://dailymed.nlm.nih.gov/dailymed/services/v2";
|
|
3
|
+
const REQUEST_DELAY_MS = 200;
|
|
4
|
+
const TIMEOUT_MS = 20000;
|
|
5
|
+
let lastRequestTime = 0;
|
|
6
|
+
async function rateLimitedFetch(url) {
|
|
7
|
+
const now = Date.now();
|
|
8
|
+
const elapsed = now - lastRequestTime;
|
|
9
|
+
if (elapsed < REQUEST_DELAY_MS) {
|
|
10
|
+
await new Promise((resolve) => setTimeout(resolve, REQUEST_DELAY_MS - elapsed));
|
|
11
|
+
}
|
|
12
|
+
lastRequestTime = Date.now();
|
|
13
|
+
const controller = new AbortController();
|
|
14
|
+
const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
throw new Error(`DailyMed API error: ${response.status} ${response.statusText}`);
|
|
19
|
+
}
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
clearTimeout(timeout);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function searchDrugLabels(drugName) {
|
|
27
|
+
const cacheKey = `dailymed:search:${drugName.toLowerCase()}`;
|
|
28
|
+
const cached = cache.get(cacheKey);
|
|
29
|
+
if (cached)
|
|
30
|
+
return cached;
|
|
31
|
+
const params = new URLSearchParams({
|
|
32
|
+
drug_name: drugName,
|
|
33
|
+
pagesize: "10",
|
|
34
|
+
});
|
|
35
|
+
const url = `${BASE_URL}/spls.json?${params}`;
|
|
36
|
+
const response = await rateLimitedFetch(url);
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
const results = (data.data ?? []).map((item) => ({
|
|
39
|
+
setid: String(item.setid ?? ""),
|
|
40
|
+
title: String(item.title ?? ""),
|
|
41
|
+
published_date: String(item.published_date ?? ""),
|
|
42
|
+
spl_version: String(item.spl_version ?? ""),
|
|
43
|
+
}));
|
|
44
|
+
cache.set(cacheKey, results, TTL.SEARCH);
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
47
|
+
export async function fetchSplXml(setid) {
|
|
48
|
+
const cacheKey = `dailymed:spl:${setid}`;
|
|
49
|
+
const cached = cache.get(cacheKey);
|
|
50
|
+
if (cached)
|
|
51
|
+
return cached;
|
|
52
|
+
const url = `${BASE_URL}/spls/${setid}.xml`;
|
|
53
|
+
const response = await rateLimitedFetch(url);
|
|
54
|
+
const text = await response.text();
|
|
55
|
+
cache.set(cacheKey, text, TTL.LABEL);
|
|
56
|
+
return text;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=dailymed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dailymed.js","sourceRoot":"","sources":["../../src/lib/dailymed.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface EmcSearchResult {
|
|
2
|
+
product_id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
company: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function searchEmc(drugName: string): Promise<EmcSearchResult[]>;
|
|
7
|
+
export declare function fetchSmpcHtml(productId: string): Promise<string>;
|
|
8
|
+
export declare function parseSmpcSections(html: string, requestedSections?: string[]): Array<{
|
|
9
|
+
code: string;
|
|
10
|
+
title: string;
|
|
11
|
+
content: string;
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=emc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emc.d.ts","sourceRoot":"","sources":["../../src/lib/emc.ts"],"names":[],"mappings":"AAqCA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAqC5E;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWtE;AA0CD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAC3B,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAsGzD"}
|
package/dist/lib/emc.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { cache, TTL } from "./cache.js";
|
|
3
|
+
const BASE_URL = "https://www.medicines.org.uk";
|
|
4
|
+
const REQUEST_DELAY_MS = 1000;
|
|
5
|
+
const TIMEOUT_MS = 20000;
|
|
6
|
+
const USER_AGENT = "PubCrawl/2.0 (pharmatools.ai; nick@pharmatools.ai)";
|
|
7
|
+
let lastRequestTime = 0;
|
|
8
|
+
async function rateLimitedFetch(url) {
|
|
9
|
+
const now = Date.now();
|
|
10
|
+
const elapsed = now - lastRequestTime;
|
|
11
|
+
if (elapsed < REQUEST_DELAY_MS) {
|
|
12
|
+
await new Promise((resolve) => setTimeout(resolve, REQUEST_DELAY_MS - elapsed));
|
|
13
|
+
}
|
|
14
|
+
lastRequestTime = Date.now();
|
|
15
|
+
const controller = new AbortController();
|
|
16
|
+
const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(url, {
|
|
19
|
+
signal: controller.signal,
|
|
20
|
+
headers: { "User-Agent": USER_AGENT },
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
throw new Error(`eMC error: ${response.status} ${response.statusText}`);
|
|
24
|
+
}
|
|
25
|
+
return response;
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
clearTimeout(timeout);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function searchEmc(drugName) {
|
|
32
|
+
const cacheKey = `emc:search:${drugName.toLowerCase()}`;
|
|
33
|
+
const cached = cache.get(cacheKey);
|
|
34
|
+
if (cached)
|
|
35
|
+
return cached;
|
|
36
|
+
const params = new URLSearchParams({ q: drugName });
|
|
37
|
+
const url = `${BASE_URL}/emc/search?${params}`;
|
|
38
|
+
const response = await rateLimitedFetch(url);
|
|
39
|
+
const html = await response.text();
|
|
40
|
+
const $ = cheerio.load(html);
|
|
41
|
+
const results = [];
|
|
42
|
+
// Parse search results — look for SmPC links (href contains /smpc)
|
|
43
|
+
$("a[href*='/emc/product/']").each((_, el) => {
|
|
44
|
+
const href = $(el).attr("href") ?? "";
|
|
45
|
+
const smpcMatch = href.match(/\/emc\/product\/(\d+)\/smpc/);
|
|
46
|
+
if (!smpcMatch)
|
|
47
|
+
return;
|
|
48
|
+
const product_id = smpcMatch[1];
|
|
49
|
+
const name = $(el).text().trim();
|
|
50
|
+
// Skip generic link text like "Health Professionals (SmPC)"
|
|
51
|
+
if (!name || name.toLowerCase().includes("health professional"))
|
|
52
|
+
return;
|
|
53
|
+
// Avoid duplicates
|
|
54
|
+
if (results.some((r) => r.product_id === product_id))
|
|
55
|
+
return;
|
|
56
|
+
// Try to find company from nearby text
|
|
57
|
+
const parent = $(el).closest("li, tr, div, article");
|
|
58
|
+
const company = parent.find(".company, .manufacturer").text().trim();
|
|
59
|
+
results.push({ product_id, name, company });
|
|
60
|
+
});
|
|
61
|
+
cache.set(cacheKey, results, TTL.SEARCH);
|
|
62
|
+
return results;
|
|
63
|
+
}
|
|
64
|
+
export async function fetchSmpcHtml(productId) {
|
|
65
|
+
const cacheKey = `emc:smpc:${productId}`;
|
|
66
|
+
const cached = cache.get(cacheKey);
|
|
67
|
+
if (cached)
|
|
68
|
+
return cached;
|
|
69
|
+
const url = `${BASE_URL}/emc/product/${productId}/smpc`;
|
|
70
|
+
const response = await rateLimitedFetch(url);
|
|
71
|
+
const html = await response.text();
|
|
72
|
+
cache.set(cacheKey, html, TTL.LABEL);
|
|
73
|
+
return html;
|
|
74
|
+
}
|
|
75
|
+
// SmPC standard section numbering
|
|
76
|
+
const SMPC_SECTION_NAMES = {
|
|
77
|
+
"4.1": "Therapeutic indications",
|
|
78
|
+
"4.2": "Posology and method of administration",
|
|
79
|
+
"4.3": "Contraindications",
|
|
80
|
+
"4.4": "Special warnings and precautions for use",
|
|
81
|
+
"4.5": "Interaction with other medicinal products",
|
|
82
|
+
"4.6": "Fertility, pregnancy and lactation",
|
|
83
|
+
"4.7": "Effects on ability to drive and use machines",
|
|
84
|
+
"4.8": "Undesirable effects",
|
|
85
|
+
"4.9": "Overdose",
|
|
86
|
+
"5.1": "Pharmacodynamic properties",
|
|
87
|
+
"5.2": "Pharmacokinetic properties",
|
|
88
|
+
"5.3": "Preclinical safety data",
|
|
89
|
+
"6.1": "List of excipients",
|
|
90
|
+
"6.2": "Incompatibilities",
|
|
91
|
+
"6.3": "Shelf life",
|
|
92
|
+
"6.4": "Special precautions for storage",
|
|
93
|
+
"6.5": "Nature and contents of container",
|
|
94
|
+
"6.6": "Special precautions for disposal",
|
|
95
|
+
};
|
|
96
|
+
function htmlToText(html) {
|
|
97
|
+
const $ = cheerio.load(html);
|
|
98
|
+
// Replace <br> with newlines
|
|
99
|
+
$("br").replaceWith("\n");
|
|
100
|
+
// Replace <li> with bullet points
|
|
101
|
+
$("li").each((_, el) => {
|
|
102
|
+
$(el).prepend("- ");
|
|
103
|
+
$(el).append("\n");
|
|
104
|
+
});
|
|
105
|
+
// Add newlines after block elements
|
|
106
|
+
$("p, div, tr, h1, h2, h3, h4, h5, h6").each((_, el) => {
|
|
107
|
+
$(el).append("\n");
|
|
108
|
+
});
|
|
109
|
+
return $.text().replace(/\n{3,}/g, "\n\n").trim();
|
|
110
|
+
}
|
|
111
|
+
export function parseSmpcSections(html, requestedSections) {
|
|
112
|
+
const $ = cheerio.load(html);
|
|
113
|
+
const results = [];
|
|
114
|
+
const sectionElements = [];
|
|
115
|
+
// Strategy 1: Look for elements with IDs or classes containing section numbers
|
|
116
|
+
$("[id*='SECTION'], [id*='section'], .sectionHeading, h2, h3, h4").each((_, el) => {
|
|
117
|
+
const text = $(el).text().trim();
|
|
118
|
+
const match = text.match(/^(\d+\.?\d*)\s+(.+)/);
|
|
119
|
+
if (match) {
|
|
120
|
+
sectionElements.push({
|
|
121
|
+
code: match[1],
|
|
122
|
+
title: match[2].trim(),
|
|
123
|
+
element: $(el),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// Strategy 2: If strategy 1 found nothing, scan all text nodes for section headers
|
|
128
|
+
if (sectionElements.length === 0) {
|
|
129
|
+
$("*").each((_, el) => {
|
|
130
|
+
const $el = $(el);
|
|
131
|
+
if ($el.children().length > 0 && !$el.is("a, span, strong, em, b, i"))
|
|
132
|
+
return;
|
|
133
|
+
const text = $el.text().trim();
|
|
134
|
+
const match = text.match(/^(\d+\.?\d*)\s+(.+)/);
|
|
135
|
+
if (match && SMPC_SECTION_NAMES[match[1]]) {
|
|
136
|
+
sectionElements.push({
|
|
137
|
+
code: match[1],
|
|
138
|
+
title: match[2].trim(),
|
|
139
|
+
element: $el,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Extract content between consecutive headings
|
|
145
|
+
for (let i = 0; i < sectionElements.length; i++) {
|
|
146
|
+
const current = sectionElements[i];
|
|
147
|
+
const next = sectionElements[i + 1];
|
|
148
|
+
// Collect all sibling content between this heading and the next
|
|
149
|
+
let content = "";
|
|
150
|
+
let node = current.element.next();
|
|
151
|
+
while (node.length > 0) {
|
|
152
|
+
if (next && node.is(next.element))
|
|
153
|
+
break;
|
|
154
|
+
const nodeHtml = $.html(node);
|
|
155
|
+
if (nodeHtml) {
|
|
156
|
+
content += htmlToText(nodeHtml) + "\n";
|
|
157
|
+
}
|
|
158
|
+
node = node.next();
|
|
159
|
+
}
|
|
160
|
+
// If no content from sibling traversal, try parent's content
|
|
161
|
+
if (!content.trim()) {
|
|
162
|
+
const parent = current.element.parent();
|
|
163
|
+
const parentHtml = $.html(parent);
|
|
164
|
+
if (parentHtml) {
|
|
165
|
+
const parentText = htmlToText(parentHtml);
|
|
166
|
+
// Remove the heading text itself
|
|
167
|
+
const headingText = current.element.text().trim();
|
|
168
|
+
content = parentText.replace(headingText, "").trim();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
results.push({
|
|
172
|
+
code: current.code,
|
|
173
|
+
title: current.title,
|
|
174
|
+
content: content.trim(),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// Filter by requested sections if specified
|
|
178
|
+
if (requestedSections && requestedSections.length > 0) {
|
|
179
|
+
const filtered = results.filter((s) => {
|
|
180
|
+
return requestedSections.some((req) => {
|
|
181
|
+
const lower = req.toLowerCase().trim();
|
|
182
|
+
// Match by section number (e.g., "4.1")
|
|
183
|
+
if (s.code === lower || s.code === req)
|
|
184
|
+
return true;
|
|
185
|
+
// Match by name substring
|
|
186
|
+
if (s.title.toLowerCase().includes(lower))
|
|
187
|
+
return true;
|
|
188
|
+
if (lower.includes("indication"))
|
|
189
|
+
return s.code === "4.1";
|
|
190
|
+
if (lower.includes("dosage") || lower.includes("dosing") || lower.includes("posology"))
|
|
191
|
+
return s.code === "4.2";
|
|
192
|
+
if (lower.includes("contraindication"))
|
|
193
|
+
return s.code === "4.3";
|
|
194
|
+
if (lower.includes("warning") || lower.includes("precaution"))
|
|
195
|
+
return s.code === "4.4";
|
|
196
|
+
if (lower.includes("interaction"))
|
|
197
|
+
return s.code === "4.5";
|
|
198
|
+
if (lower.includes("pregnancy") || lower.includes("fertility"))
|
|
199
|
+
return s.code === "4.6";
|
|
200
|
+
if (lower.includes("adverse") || lower.includes("undesirable") || lower.includes("side effect"))
|
|
201
|
+
return s.code === "4.8";
|
|
202
|
+
if (lower.includes("overdose") || lower.includes("overdosage"))
|
|
203
|
+
return s.code === "4.9";
|
|
204
|
+
if (lower.includes("pharmacodynamic"))
|
|
205
|
+
return s.code === "5.1";
|
|
206
|
+
if (lower.includes("pharmacokinetic"))
|
|
207
|
+
return s.code === "5.2";
|
|
208
|
+
return false;
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
return filtered;
|
|
212
|
+
}
|
|
213
|
+
return results;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=emc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emc.js","sourceRoot":"","sources":["../../src/lib/emc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface SectionMapping {
|
|
2
|
+
topic: string;
|
|
3
|
+
us_loinc: string;
|
|
4
|
+
uk_code: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const SECTION_MAP: SectionMapping[];
|
|
7
|
+
export declare function filterSectionMap(requestedTopics?: string[]): SectionMapping[];
|
|
8
|
+
//# sourceMappingURL=label-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label-mapping.d.ts","sourceRoot":"","sources":["../../src/lib/label-mapping.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,WAAW,EAAE,cAAc,EAUvC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAc7E"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const SECTION_MAP = [
|
|
2
|
+
{ topic: "Indications", us_loinc: "34067-9", uk_code: "4.1" },
|
|
3
|
+
{ topic: "Dosing", us_loinc: "34068-7", uk_code: "4.2" },
|
|
4
|
+
{ topic: "Contraindications", us_loinc: "34070-3", uk_code: "4.3" },
|
|
5
|
+
{ topic: "Warnings", us_loinc: "43685-7", uk_code: "4.4" },
|
|
6
|
+
{ topic: "Drug Interactions", us_loinc: "34073-7", uk_code: "4.5" },
|
|
7
|
+
{ topic: "Pregnancy", us_loinc: "42228-7", uk_code: "4.6" },
|
|
8
|
+
{ topic: "Adverse Reactions", us_loinc: "34084-4", uk_code: "4.8" },
|
|
9
|
+
{ topic: "Overdosage", us_loinc: "34088-5", uk_code: "4.9" },
|
|
10
|
+
{ topic: "Clinical Pharmacology", us_loinc: "34090-1", uk_code: "5.1" },
|
|
11
|
+
];
|
|
12
|
+
export function filterSectionMap(requestedTopics) {
|
|
13
|
+
if (!requestedTopics || requestedTopics.length === 0)
|
|
14
|
+
return SECTION_MAP;
|
|
15
|
+
return SECTION_MAP.filter((mapping) => requestedTopics.some((req) => {
|
|
16
|
+
const lower = req.toLowerCase().trim();
|
|
17
|
+
return (mapping.topic.toLowerCase().includes(lower) ||
|
|
18
|
+
lower.includes(mapping.topic.toLowerCase()) ||
|
|
19
|
+
mapping.us_loinc === req ||
|
|
20
|
+
mapping.uk_code === req);
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=label-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label-mapping.js","sourceRoot":"","sources":["../../src/lib/label-mapping.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,WAAW,GAAqB;IAC3C,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;IAC7D,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;IACxD,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;IACnE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;IAC1D,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;IACnE,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;IAC3D,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;IACnE,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;IAC5D,EAAE,KAAK,EAAE,uBAAuB,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;CACxE,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,eAA0B;IACzD,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IAEzE,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CACpC,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QACvC,OAAO,CACL,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC3C,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAC3C,OAAO,CAAC,QAAQ,KAAK,GAAG;YACxB,OAAO,CAAC,OAAO,KAAK,GAAG,CACxB,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC"}
|