n8n-nodes-vetresearch 1.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/dist/credentials/PubMedApi.credentials.d.ts +6 -0
- package/dist/credentials/PubMedApi.credentials.js +20 -0
- package/dist/nodes/PubMedNode/PubMedNode.node.d.ts +5 -0
- package/dist/nodes/PubMedNode/PubMedNode.node.js +91 -0
- package/package.json +31 -0
- package/src/credentials/PubMedApi.credentials.ts +16 -0
- package/src/nodes/PubMedNode/PubMedNode.node.ts +97 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PubMedApi = void 0;
|
|
4
|
+
class PubMedApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'pubMedApi';
|
|
7
|
+
this.displayName = 'PubMed API';
|
|
8
|
+
this.properties = [
|
|
9
|
+
{
|
|
10
|
+
displayName: 'API Key (optionnel)',
|
|
11
|
+
name: 'apiKey',
|
|
12
|
+
type: 'string',
|
|
13
|
+
typeOptions: { password: true },
|
|
14
|
+
default: '',
|
|
15
|
+
description: 'Optionnel — sans clé la limite est 3 req/sec, avec clé 10 req/sec',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.PubMedApi = PubMedApi;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PubMedNode = void 0;
|
|
4
|
+
class PubMedNode {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.description = {
|
|
7
|
+
displayName: 'PubMed Search',
|
|
8
|
+
name: 'pubMedSearch',
|
|
9
|
+
group: ['transform'],
|
|
10
|
+
version: 1,
|
|
11
|
+
description: 'Search scientific publications via PubMed',
|
|
12
|
+
defaults: { name: 'PubMed Search' },
|
|
13
|
+
credentials: [
|
|
14
|
+
{
|
|
15
|
+
name: 'pubMedApi',
|
|
16
|
+
required: false,
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
inputs: ['main'],
|
|
20
|
+
outputs: ['main'],
|
|
21
|
+
properties: [
|
|
22
|
+
{
|
|
23
|
+
displayName: 'Search Query',
|
|
24
|
+
name: 'query',
|
|
25
|
+
type: 'string',
|
|
26
|
+
default: '',
|
|
27
|
+
placeholder: 'feline coronavirus vaccine',
|
|
28
|
+
description: 'PubMed search query',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
displayName: 'Max Results',
|
|
32
|
+
name: 'maxResults',
|
|
33
|
+
type: 'number',
|
|
34
|
+
default: 10,
|
|
35
|
+
typeOptions: { minValue: 1, maxValue: 100 },
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
displayName: 'Date Range',
|
|
39
|
+
name: 'dateRange',
|
|
40
|
+
type: 'options',
|
|
41
|
+
options: [
|
|
42
|
+
{ name: 'Last Year', value: '1' },
|
|
43
|
+
{ name: 'Last 3 Years', value: '3' },
|
|
44
|
+
{ name: 'Last 5 Years', value: '5' },
|
|
45
|
+
{ name: 'All Time', value: '0' },
|
|
46
|
+
],
|
|
47
|
+
default: '3',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async execute() {
|
|
53
|
+
const query = this.getNodeParameter('query', 0);
|
|
54
|
+
const maxResults = this.getNodeParameter('maxResults', 0);
|
|
55
|
+
const dateRange = this.getNodeParameter('dateRange', 0);
|
|
56
|
+
// Étape 1 : récupérer les IDs
|
|
57
|
+
let searchUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmode=json&retmax=${maxResults}&term=${encodeURIComponent(query)}`;
|
|
58
|
+
if (dateRange !== '0') {
|
|
59
|
+
searchUrl += `&reldate=${parseInt(dateRange) * 365}&datetype=pdat`;
|
|
60
|
+
}
|
|
61
|
+
const searchResp = await this.helpers.httpRequest({
|
|
62
|
+
method: 'GET',
|
|
63
|
+
url: searchUrl,
|
|
64
|
+
});
|
|
65
|
+
const ids = searchResp.esearchresult.idlist;
|
|
66
|
+
if (!ids.length)
|
|
67
|
+
return [[]];
|
|
68
|
+
// Étape 2 : récupérer les détails (summary JSON)
|
|
69
|
+
const summaryUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&retmode=json&id=${ids.join(',')}`;
|
|
70
|
+
const summaryResp = await this.helpers.httpRequest({
|
|
71
|
+
method: 'GET',
|
|
72
|
+
url: summaryUrl,
|
|
73
|
+
});
|
|
74
|
+
const results = ids.map((id) => {
|
|
75
|
+
var _a;
|
|
76
|
+
const doc = summaryResp.result[id];
|
|
77
|
+
return {
|
|
78
|
+
json: {
|
|
79
|
+
pmid: id,
|
|
80
|
+
title: (doc === null || doc === void 0 ? void 0 : doc.title) || '',
|
|
81
|
+
authors: ((_a = doc === null || doc === void 0 ? void 0 : doc.authors) === null || _a === void 0 ? void 0 : _a.map((a) => a.name).join(', ')) || '',
|
|
82
|
+
journal: (doc === null || doc === void 0 ? void 0 : doc.fulljournalname) || '',
|
|
83
|
+
pubDate: (doc === null || doc === void 0 ? void 0 : doc.pubdate) || '',
|
|
84
|
+
url: `https://pubmed.ncbi.nlm.nih.gov/${id}/`,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
return [results];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.PubMedNode = PubMedNode;
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-vetresearch",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"dev": "tsc --watch"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"type": "commonjs",
|
|
14
|
+
"n8n": {
|
|
15
|
+
"n8nNodesApiVersion": 1,
|
|
16
|
+
"credentials": [
|
|
17
|
+
"dist/credentials/PubMedApi.credentials.js"
|
|
18
|
+
],
|
|
19
|
+
"nodes": [
|
|
20
|
+
"dist/nodes/PubMedNode/PubMedNode.node.js"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"n8n-workflow": "^2.16.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^25.9.3",
|
|
28
|
+
"ts-node": "^10.9.2",
|
|
29
|
+
"typescript": "^6.0.3"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
|
|
3
|
+
export class PubMedApi implements ICredentialType {
|
|
4
|
+
name = 'pubMedApi';
|
|
5
|
+
displayName = 'PubMed API';
|
|
6
|
+
properties: INodeProperties[] = [
|
|
7
|
+
{
|
|
8
|
+
displayName: 'API Key (optionnel)',
|
|
9
|
+
name: 'apiKey',
|
|
10
|
+
type: 'string',
|
|
11
|
+
typeOptions: { password: true },
|
|
12
|
+
default: '',
|
|
13
|
+
description: 'Optionnel — sans clé la limite est 3 req/sec, avec clé 10 req/sec',
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IExecuteFunctions,
|
|
3
|
+
INodeExecutionData,
|
|
4
|
+
INodeType,
|
|
5
|
+
INodeTypeDescription,
|
|
6
|
+
} from 'n8n-workflow';
|
|
7
|
+
|
|
8
|
+
export class PubMedNode implements INodeType {
|
|
9
|
+
description: INodeTypeDescription = {
|
|
10
|
+
displayName: 'PubMed Search',
|
|
11
|
+
name: 'pubMedSearch',
|
|
12
|
+
group: ['transform'],
|
|
13
|
+
version: 1,
|
|
14
|
+
description: 'Search scientific publications via PubMed',
|
|
15
|
+
defaults: { name: 'PubMed Search' },
|
|
16
|
+
credentials: [
|
|
17
|
+
{
|
|
18
|
+
name: 'pubMedApi',
|
|
19
|
+
required: false,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
inputs: ['main'] as any,
|
|
23
|
+
outputs: ['main'] as any,
|
|
24
|
+
properties: [
|
|
25
|
+
{
|
|
26
|
+
displayName: 'Search Query',
|
|
27
|
+
name: 'query',
|
|
28
|
+
type: 'string',
|
|
29
|
+
default: '',
|
|
30
|
+
placeholder: 'feline coronavirus vaccine',
|
|
31
|
+
description: 'PubMed search query',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
displayName: 'Max Results',
|
|
35
|
+
name: 'maxResults',
|
|
36
|
+
type: 'number',
|
|
37
|
+
default: 10,
|
|
38
|
+
typeOptions: { minValue: 1, maxValue: 100 },
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
displayName: 'Date Range',
|
|
42
|
+
name: 'dateRange',
|
|
43
|
+
type: 'options',
|
|
44
|
+
options: [
|
|
45
|
+
{ name: 'Last Year', value: '1' },
|
|
46
|
+
{ name: 'Last 3 Years', value: '3' },
|
|
47
|
+
{ name: 'Last 5 Years', value: '5' },
|
|
48
|
+
{ name: 'All Time', value: '0' },
|
|
49
|
+
],
|
|
50
|
+
default: '3',
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
56
|
+
const query = this.getNodeParameter('query', 0) as string;
|
|
57
|
+
const maxResults = this.getNodeParameter('maxResults', 0) as number;
|
|
58
|
+
const dateRange = this.getNodeParameter('dateRange', 0) as string;
|
|
59
|
+
|
|
60
|
+
// Étape 1 : récupérer les IDs
|
|
61
|
+
let searchUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmode=json&retmax=${maxResults}&term=${encodeURIComponent(query)}`;
|
|
62
|
+
if (dateRange !== '0') {
|
|
63
|
+
searchUrl += `&reldate=${parseInt(dateRange) * 365}&datetype=pdat`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const searchResp = await this.helpers.httpRequest({
|
|
67
|
+
method: 'GET',
|
|
68
|
+
url: searchUrl,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const ids: string[] = searchResp.esearchresult.idlist;
|
|
72
|
+
if (!ids.length) return [[]];
|
|
73
|
+
|
|
74
|
+
// Étape 2 : récupérer les détails (summary JSON)
|
|
75
|
+
const summaryUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&retmode=json&id=${ids.join(',')}`;
|
|
76
|
+
const summaryResp = await this.helpers.httpRequest({
|
|
77
|
+
method: 'GET',
|
|
78
|
+
url: summaryUrl,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const results: INodeExecutionData[] = ids.map((id) => {
|
|
82
|
+
const doc = summaryResp.result[id];
|
|
83
|
+
return {
|
|
84
|
+
json: {
|
|
85
|
+
pmid: id,
|
|
86
|
+
title: doc?.title || '',
|
|
87
|
+
authors: doc?.authors?.map((a: any) => a.name).join(', ') || '',
|
|
88
|
+
journal: doc?.fulljournalname || '',
|
|
89
|
+
pubDate: doc?.pubdate || '',
|
|
90
|
+
url: `https://pubmed.ncbi.nlm.nih.gov/${id}/`,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return [results];
|
|
96
|
+
}
|
|
97
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2019",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2019"],
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"rootDir": "./src",
|
|
9
|
+
"strict": false,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"skipLibCheck": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"],
|
|
15
|
+
"exclude": ["node_modules", "dist"]
|
|
16
|
+
}
|