@pdfvector/instance-contract 0.0.28 → 0.0.30
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/.tsc/lib/router/academic/find-citations.d.ts +1 -0
- package/.tsc/lib/router/academic/find-citations.js +2 -1
- package/.tsc/lib/router/academic/index.d.ts +3 -0
- package/.tsc/lib/router/academic/index.js +3 -0
- package/.tsc/lib/router/academic/paper-graph.d.ts +85 -0
- package/.tsc/lib/router/academic/paper-graph.js +140 -0
- package/.tsc/lib/router/academic/search-grants.d.ts +78 -0
- package/.tsc/lib/router/academic/search-grants.js +170 -0
- package/.tsc/lib/router/academic/search.d.ts +2 -0
- package/.tsc/lib/router/academic/search.js +2 -1
- package/.tsc/lib/router/academic/similar-papers.d.ts +70 -0
- package/.tsc/lib/router/academic/similar-papers.js +139 -0
- package/CHANGELOG.md +14 -0
- package/package.json +1 -1
|
@@ -8,8 +8,9 @@ const providerSchema = z.enum([
|
|
|
8
8
|
"eric",
|
|
9
9
|
"europe-pmc",
|
|
10
10
|
"openalex",
|
|
11
|
+
"crossref",
|
|
11
12
|
], {
|
|
12
|
-
message: "Invalid provider. Must be one of: semantic-scholar, pubmed, arxiv, google-scholar, eric, europe-pmc, openalex",
|
|
13
|
+
message: "Invalid provider. Must be one of: semantic-scholar, pubmed, arxiv, google-scholar, eric, europe-pmc, openalex, crossref",
|
|
13
14
|
});
|
|
14
15
|
const authorSchema = z.object({
|
|
15
16
|
name: z.string(),
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const paperGraph: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
citationsLimit: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
referencesLimit: z.ZodDefault<z.ZodNumber>;
|
|
6
|
+
citationsOffset: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
referencesOffset: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
fields: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodEnum<{
|
|
9
|
+
url: "url";
|
|
10
|
+
doi: "doi";
|
|
11
|
+
title: "title";
|
|
12
|
+
providerURL: "providerURL";
|
|
13
|
+
date: "date";
|
|
14
|
+
authors: "authors";
|
|
15
|
+
year: "year";
|
|
16
|
+
totalCitations: "totalCitations";
|
|
17
|
+
totalReferences: "totalReferences";
|
|
18
|
+
abstract: "abstract";
|
|
19
|
+
pdfURL: "pdfURL";
|
|
20
|
+
provider: "provider";
|
|
21
|
+
providerData: "providerData";
|
|
22
|
+
}>>>>;
|
|
23
|
+
callback: z.ZodOptional<z.ZodObject<{
|
|
24
|
+
url: z.ZodURL;
|
|
25
|
+
type: z.ZodOptional<z.ZodString>;
|
|
26
|
+
}, z.core.$strip>>;
|
|
27
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
28
|
+
paper: z.ZodObject<{
|
|
29
|
+
doi: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
30
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
31
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
32
|
+
providerURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
33
|
+
authors: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
34
|
+
name: z.ZodString;
|
|
35
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
36
|
+
}, z.core.$strip>>>>;
|
|
37
|
+
date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
38
|
+
year: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
39
|
+
totalCitations: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
40
|
+
totalReferences: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
41
|
+
abstract: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
42
|
+
pdfURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
43
|
+
provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
44
|
+
providerData: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
45
|
+
}, z.core.$strip>;
|
|
46
|
+
citations: z.ZodArray<z.ZodObject<{
|
|
47
|
+
doi: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
48
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
49
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
50
|
+
providerURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
51
|
+
authors: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
52
|
+
name: z.ZodString;
|
|
53
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
54
|
+
}, z.core.$strip>>>>;
|
|
55
|
+
date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
56
|
+
year: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
57
|
+
totalCitations: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
58
|
+
totalReferences: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
59
|
+
abstract: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
60
|
+
pdfURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
61
|
+
provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
62
|
+
providerData: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
references: z.ZodArray<z.ZodObject<{
|
|
65
|
+
doi: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
66
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
67
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
68
|
+
providerURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
69
|
+
authors: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
70
|
+
name: z.ZodString;
|
|
71
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
72
|
+
}, z.core.$strip>>>>;
|
|
73
|
+
date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
74
|
+
year: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
75
|
+
totalCitations: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
76
|
+
totalReferences: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
77
|
+
abstract: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
78
|
+
pdfURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
79
|
+
provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
80
|
+
providerData: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
81
|
+
}, z.core.$strip>>;
|
|
82
|
+
totalCitations: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
83
|
+
totalReferences: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
84
|
+
requestId: z.ZodNumber;
|
|
85
|
+
}, z.core.$strip>, Record<never, never>, Record<never, never>>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const authorSchema = z.object({
|
|
4
|
+
name: z.string(),
|
|
5
|
+
url: z.string().nullish(),
|
|
6
|
+
});
|
|
7
|
+
const publicationSchema = z.object({
|
|
8
|
+
doi: z.string().nullish(),
|
|
9
|
+
title: z.string().nullish(),
|
|
10
|
+
url: z.string().nullish(),
|
|
11
|
+
providerURL: z.string().nullish(),
|
|
12
|
+
authors: z.array(authorSchema).nullish(),
|
|
13
|
+
date: z.string().nullish(),
|
|
14
|
+
year: z.number().nullish(),
|
|
15
|
+
totalCitations: z.number().nullish(),
|
|
16
|
+
totalReferences: z.number().nullish(),
|
|
17
|
+
abstract: z.string().nullish(),
|
|
18
|
+
pdfURL: z.string().nullish(),
|
|
19
|
+
provider: z.string().nullish(),
|
|
20
|
+
providerData: z.record(z.string(), z.unknown()).nullish(),
|
|
21
|
+
});
|
|
22
|
+
const requestExamples = {
|
|
23
|
+
"Get citations by DOI": {
|
|
24
|
+
summary: "Get citations and references for a paper by DOI",
|
|
25
|
+
value: {
|
|
26
|
+
id: "10.1038/nature12373",
|
|
27
|
+
citationsLimit: 20,
|
|
28
|
+
referencesLimit: 20,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
"Get citations by ArXiv ID": {
|
|
32
|
+
summary: "Get citations and references for an ArXiv paper",
|
|
33
|
+
value: {
|
|
34
|
+
id: "2303.08774",
|
|
35
|
+
citationsLimit: 50,
|
|
36
|
+
referencesLimit: 50,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
"Paginated citations": {
|
|
40
|
+
summary: "Page through a paper's citations",
|
|
41
|
+
value: {
|
|
42
|
+
id: "10.1038/nature12373",
|
|
43
|
+
citationsLimit: 20,
|
|
44
|
+
citationsOffset: 20,
|
|
45
|
+
referencesLimit: 0,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
export const paperGraph = oc
|
|
50
|
+
.input(z.object({
|
|
51
|
+
id: z
|
|
52
|
+
.string({ message: "id is required and must be a string" })
|
|
53
|
+
.min(1, "id must not be empty")
|
|
54
|
+
.max(500, "id must be at most 500 characters")
|
|
55
|
+
.describe("Paper identifier. Supports DOI, Semantic Scholar ID, ArXiv ID, PubMed ID, OpenAlex ID, or URL."),
|
|
56
|
+
citationsLimit: z
|
|
57
|
+
.number({ message: "citationsLimit must be a number" })
|
|
58
|
+
.int("citationsLimit must be a whole number")
|
|
59
|
+
.min(0, "citationsLimit must be 0 or greater")
|
|
60
|
+
.max(1000, "citationsLimit must be at most 1000")
|
|
61
|
+
.default(100)
|
|
62
|
+
.describe("Maximum number of citing papers to return"),
|
|
63
|
+
referencesLimit: z
|
|
64
|
+
.number({ message: "referencesLimit must be a number" })
|
|
65
|
+
.int("referencesLimit must be a whole number")
|
|
66
|
+
.min(0, "referencesLimit must be 0 or greater")
|
|
67
|
+
.max(1000, "referencesLimit must be at most 1000")
|
|
68
|
+
.default(100)
|
|
69
|
+
.describe("Maximum number of referenced papers to return"),
|
|
70
|
+
citationsOffset: z
|
|
71
|
+
.number({ message: "citationsOffset must be a number" })
|
|
72
|
+
.int("citationsOffset must be a whole number")
|
|
73
|
+
.min(0, "citationsOffset must be 0 or greater")
|
|
74
|
+
.default(0)
|
|
75
|
+
.describe("Pagination offset for citations"),
|
|
76
|
+
referencesOffset: z
|
|
77
|
+
.number({ message: "referencesOffset must be a number" })
|
|
78
|
+
.int("referencesOffset must be a whole number")
|
|
79
|
+
.min(0, "referencesOffset must be 0 or greater")
|
|
80
|
+
.default(0)
|
|
81
|
+
.describe("Pagination offset for references"),
|
|
82
|
+
fields: z
|
|
83
|
+
.array(z.enum([
|
|
84
|
+
"doi",
|
|
85
|
+
"title",
|
|
86
|
+
"url",
|
|
87
|
+
"providerURL",
|
|
88
|
+
"authors",
|
|
89
|
+
"date",
|
|
90
|
+
"year",
|
|
91
|
+
"totalCitations",
|
|
92
|
+
"totalReferences",
|
|
93
|
+
"abstract",
|
|
94
|
+
"pdfURL",
|
|
95
|
+
"provider",
|
|
96
|
+
"providerData",
|
|
97
|
+
]), {
|
|
98
|
+
message: "fields must be an array of valid publication field names",
|
|
99
|
+
})
|
|
100
|
+
.nullish()
|
|
101
|
+
.describe("Specific publication fields to return. If omitted, returns all fields except providerData."),
|
|
102
|
+
callback: z
|
|
103
|
+
.object({
|
|
104
|
+
url: z
|
|
105
|
+
.url()
|
|
106
|
+
.describe("Webhook URL where results will be POSTed when processing completes"),
|
|
107
|
+
type: z
|
|
108
|
+
.string()
|
|
109
|
+
.optional()
|
|
110
|
+
.describe("Callback type identifier (e.g. 'zapier')"),
|
|
111
|
+
})
|
|
112
|
+
.optional()
|
|
113
|
+
.describe("Optional webhook callback for async processing. " +
|
|
114
|
+
"When provided, the server returns 202 immediately and POSTs the full response payload to the callback URL when processing completes. " +
|
|
115
|
+
"On error, the callback receives a POST with X-Pdfvector-Callback-Failed: true header and error details in the body. " +
|
|
116
|
+
"Useful for long-running operations that may exceed client timeout limits."),
|
|
117
|
+
}))
|
|
118
|
+
.output(z.object({
|
|
119
|
+
paper: publicationSchema,
|
|
120
|
+
citations: z.array(publicationSchema),
|
|
121
|
+
references: z.array(publicationSchema),
|
|
122
|
+
totalCitations: z.number().int().nullish(),
|
|
123
|
+
totalReferences: z.number().int().nullish(),
|
|
124
|
+
requestId: z.number().int(),
|
|
125
|
+
}))
|
|
126
|
+
.route({
|
|
127
|
+
summary: "Get paper citations and references",
|
|
128
|
+
description: "Fetch a paper's citing papers and referenced papers as full publication objects with automatic provider detection and pagination support.",
|
|
129
|
+
tags: ["Academic"],
|
|
130
|
+
spec: (op) => {
|
|
131
|
+
op.security = [{ bearerAuth: [] }];
|
|
132
|
+
const reqBody = op.requestBody;
|
|
133
|
+
if (reqBody?.content) {
|
|
134
|
+
for (const mediaType of Object.values(reqBody.content)) {
|
|
135
|
+
mediaType.examples = requestExamples;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return op;
|
|
139
|
+
},
|
|
140
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const searchGrants: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
|
|
3
|
+
query: z.ZodString;
|
|
4
|
+
providers: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
5
|
+
"grants-gov": "grants-gov";
|
|
6
|
+
"nih-reporter": "nih-reporter";
|
|
7
|
+
cordis: "cordis";
|
|
8
|
+
ukri: "ukri";
|
|
9
|
+
}>>>;
|
|
10
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
12
|
+
deadlineFrom: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
13
|
+
deadlineTo: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
14
|
+
fundingMin: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
15
|
+
fundingMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
16
|
+
fields: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodEnum<{
|
|
17
|
+
url: "url";
|
|
18
|
+
title: "title";
|
|
19
|
+
provider: "provider";
|
|
20
|
+
providerData: "providerData";
|
|
21
|
+
description: "description";
|
|
22
|
+
sourceId: "sourceId";
|
|
23
|
+
agency: "agency";
|
|
24
|
+
program: "program";
|
|
25
|
+
eligibility: "eligibility";
|
|
26
|
+
fundingAmountMin: "fundingAmountMin";
|
|
27
|
+
fundingAmountMax: "fundingAmountMax";
|
|
28
|
+
currency: "currency";
|
|
29
|
+
deadlineDate: "deadlineDate";
|
|
30
|
+
openDate: "openDate";
|
|
31
|
+
closeDate: "closeDate";
|
|
32
|
+
grantType: "grantType";
|
|
33
|
+
region: "region";
|
|
34
|
+
keywords: "keywords";
|
|
35
|
+
piName: "piName";
|
|
36
|
+
organizationName: "organizationName";
|
|
37
|
+
}>>>>;
|
|
38
|
+
callback: z.ZodOptional<z.ZodObject<{
|
|
39
|
+
url: z.ZodURL;
|
|
40
|
+
type: z.ZodOptional<z.ZodString>;
|
|
41
|
+
}, z.core.$strip>>;
|
|
42
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
43
|
+
estimatedTotalResults: z.ZodNumber;
|
|
44
|
+
results: z.ZodArray<z.ZodObject<{
|
|
45
|
+
sourceId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
46
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
47
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
48
|
+
agency: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
49
|
+
program: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
50
|
+
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
51
|
+
eligibility: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
52
|
+
fundingAmountMin: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
53
|
+
fundingAmountMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
54
|
+
currency: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
55
|
+
deadlineDate: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
56
|
+
openDate: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
57
|
+
closeDate: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
58
|
+
grantType: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
59
|
+
region: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
60
|
+
keywords: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
61
|
+
piName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
62
|
+
organizationName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
63
|
+
provider: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
64
|
+
"grants-gov": "grants-gov";
|
|
65
|
+
"nih-reporter": "nih-reporter";
|
|
66
|
+
cordis: "cordis";
|
|
67
|
+
ukri: "ukri";
|
|
68
|
+
}>>>;
|
|
69
|
+
providerData: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
70
|
+
}, z.core.$strip>>;
|
|
71
|
+
errors: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
72
|
+
provider: z.ZodString;
|
|
73
|
+
message: z.ZodString;
|
|
74
|
+
code: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
75
|
+
details: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
76
|
+
}, z.core.$strip>>>>;
|
|
77
|
+
requestId: z.ZodNumber;
|
|
78
|
+
}, z.core.$strip>, Record<never, never>, Record<never, never>>;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const grantProviderSchema = z.enum(["grants-gov", "nih-reporter", "cordis", "ukri"], {
|
|
4
|
+
message: "Invalid provider. Must be one of: grants-gov, nih-reporter, cordis, ukri",
|
|
5
|
+
});
|
|
6
|
+
const grantSchema = z.object({
|
|
7
|
+
sourceId: z.string().nullish(),
|
|
8
|
+
title: z.string().nullish(),
|
|
9
|
+
url: z.string().nullish(),
|
|
10
|
+
agency: z.string().nullish(),
|
|
11
|
+
program: z.string().nullish(),
|
|
12
|
+
description: z.string().nullish(),
|
|
13
|
+
eligibility: z.string().nullish(),
|
|
14
|
+
fundingAmountMin: z.number().nullish(),
|
|
15
|
+
fundingAmountMax: z.number().nullish(),
|
|
16
|
+
currency: z.string().nullish(),
|
|
17
|
+
deadlineDate: z.string().nullish(),
|
|
18
|
+
openDate: z.string().nullish(),
|
|
19
|
+
closeDate: z.string().nullish(),
|
|
20
|
+
grantType: z.string().nullish(),
|
|
21
|
+
region: z.string().nullish(),
|
|
22
|
+
keywords: z.array(z.string()).nullish(),
|
|
23
|
+
piName: z.string().nullish(),
|
|
24
|
+
organizationName: z.string().nullish(),
|
|
25
|
+
provider: grantProviderSchema.nullish(),
|
|
26
|
+
providerData: z.record(z.string(), z.unknown()).nullish(),
|
|
27
|
+
});
|
|
28
|
+
const providerErrorSchema = z.object({
|
|
29
|
+
provider: z.string(),
|
|
30
|
+
message: z.string(),
|
|
31
|
+
code: z.string().nullish(),
|
|
32
|
+
details: z.record(z.string(), z.unknown()).nullish(),
|
|
33
|
+
});
|
|
34
|
+
const requestExamples = {
|
|
35
|
+
"Search all providers": {
|
|
36
|
+
summary: "Search grants across all funding databases",
|
|
37
|
+
value: {
|
|
38
|
+
query: "machine learning healthcare",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
"Search with filters": {
|
|
42
|
+
summary: "Search with funding and deadline filters",
|
|
43
|
+
value: {
|
|
44
|
+
query: "climate change research",
|
|
45
|
+
providers: ["grants-gov", "cordis"],
|
|
46
|
+
fundingMin: 50000,
|
|
47
|
+
fundingMax: 500000,
|
|
48
|
+
deadlineFrom: "2026-01-01",
|
|
49
|
+
deadlineTo: "2026-12-31",
|
|
50
|
+
limit: 20,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
"Search specific provider": {
|
|
54
|
+
summary: "Search NIH grants only",
|
|
55
|
+
value: {
|
|
56
|
+
query: "CRISPR gene therapy",
|
|
57
|
+
providers: ["nih-reporter"],
|
|
58
|
+
limit: 10,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
export const searchGrants = oc
|
|
63
|
+
.input(z.object({
|
|
64
|
+
query: z
|
|
65
|
+
.string({ message: "query is required and must be a string" })
|
|
66
|
+
.min(1, "query must not be empty")
|
|
67
|
+
.max(400, "query must be at most 400 characters")
|
|
68
|
+
.describe("Search query string for grants"),
|
|
69
|
+
providers: z
|
|
70
|
+
.array(grantProviderSchema, {
|
|
71
|
+
message: "providers must be an array of valid grant provider names",
|
|
72
|
+
})
|
|
73
|
+
.default(["grants-gov", "nih-reporter", "cordis", "ukri"])
|
|
74
|
+
.describe("Grant databases to search. Defaults to all providers."),
|
|
75
|
+
offset: z
|
|
76
|
+
.number({ message: "offset must be a number" })
|
|
77
|
+
.int("offset must be a whole number")
|
|
78
|
+
.min(0, "offset must be 0 or greater")
|
|
79
|
+
.default(0)
|
|
80
|
+
.describe("Results offset for pagination"),
|
|
81
|
+
limit: z
|
|
82
|
+
.number({ message: "limit must be a number" })
|
|
83
|
+
.int("limit must be a whole number")
|
|
84
|
+
.min(1, "limit must be at least 1")
|
|
85
|
+
.max(50, "limit must be at most 50")
|
|
86
|
+
.default(10)
|
|
87
|
+
.describe("Maximum results per provider"),
|
|
88
|
+
deadlineFrom: z
|
|
89
|
+
.string()
|
|
90
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/, "deadlineFrom must be in ISO date format (YYYY-MM-DD)")
|
|
91
|
+
.nullish()
|
|
92
|
+
.describe("Filter grants with deadlines from this date (ISO format, e.g. 2026-01-01)"),
|
|
93
|
+
deadlineTo: z
|
|
94
|
+
.string()
|
|
95
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/, "deadlineTo must be in ISO date format (YYYY-MM-DD)")
|
|
96
|
+
.nullish()
|
|
97
|
+
.describe("Filter grants with deadlines up to this date (ISO format, e.g. 2026-12-31)"),
|
|
98
|
+
fundingMin: z
|
|
99
|
+
.number({ message: "fundingMin must be a number" })
|
|
100
|
+
.min(0, "fundingMin must be 0 or greater")
|
|
101
|
+
.nullish()
|
|
102
|
+
.describe("Minimum funding amount filter"),
|
|
103
|
+
fundingMax: z
|
|
104
|
+
.number({ message: "fundingMax must be a number" })
|
|
105
|
+
.min(0, "fundingMax must be 0 or greater")
|
|
106
|
+
.nullish()
|
|
107
|
+
.describe("Maximum funding amount filter"),
|
|
108
|
+
fields: z
|
|
109
|
+
.array(z.enum([
|
|
110
|
+
"sourceId",
|
|
111
|
+
"title",
|
|
112
|
+
"url",
|
|
113
|
+
"agency",
|
|
114
|
+
"program",
|
|
115
|
+
"description",
|
|
116
|
+
"eligibility",
|
|
117
|
+
"fundingAmountMin",
|
|
118
|
+
"fundingAmountMax",
|
|
119
|
+
"currency",
|
|
120
|
+
"deadlineDate",
|
|
121
|
+
"openDate",
|
|
122
|
+
"closeDate",
|
|
123
|
+
"grantType",
|
|
124
|
+
"region",
|
|
125
|
+
"keywords",
|
|
126
|
+
"piName",
|
|
127
|
+
"organizationName",
|
|
128
|
+
"provider",
|
|
129
|
+
"providerData",
|
|
130
|
+
]), {
|
|
131
|
+
message: "fields must be an array of valid grant field names",
|
|
132
|
+
})
|
|
133
|
+
.nullish()
|
|
134
|
+
.describe("Specific grant fields to return. If omitted, returns all fields except providerData."),
|
|
135
|
+
callback: z
|
|
136
|
+
.object({
|
|
137
|
+
url: z
|
|
138
|
+
.url()
|
|
139
|
+
.describe("Webhook URL where results will be POSTed when processing completes"),
|
|
140
|
+
type: z
|
|
141
|
+
.string()
|
|
142
|
+
.optional()
|
|
143
|
+
.describe("Callback type identifier (e.g. 'zapier')"),
|
|
144
|
+
})
|
|
145
|
+
.optional()
|
|
146
|
+
.describe("Optional webhook callback for async processing. " +
|
|
147
|
+
"When provided, the server returns 202 immediately and POSTs the full response payload to the callback URL when processing completes. " +
|
|
148
|
+
"On error, the callback receives a POST with X-Pdfvector-Callback-Failed: true header and error details in the body."),
|
|
149
|
+
}))
|
|
150
|
+
.output(z.object({
|
|
151
|
+
estimatedTotalResults: z.number(),
|
|
152
|
+
results: z.array(grantSchema),
|
|
153
|
+
errors: z.array(providerErrorSchema).nullish(),
|
|
154
|
+
requestId: z.number().int(),
|
|
155
|
+
}))
|
|
156
|
+
.route({
|
|
157
|
+
summary: "Search grants",
|
|
158
|
+
description: "Search for research grants and funding opportunities across multiple databases (Grants.gov, NIH RePORTER, CORDIS, UKRI) with unified results, relevance ranking, and filtering by deadline and funding amount.",
|
|
159
|
+
tags: ["Grant"],
|
|
160
|
+
spec: (op) => {
|
|
161
|
+
op.security = [{ bearerAuth: [] }];
|
|
162
|
+
const reqBody = op.requestBody;
|
|
163
|
+
if (reqBody?.content) {
|
|
164
|
+
for (const mediaType of Object.values(reqBody.content)) {
|
|
165
|
+
mediaType.examples = requestExamples;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return op;
|
|
169
|
+
},
|
|
170
|
+
});
|
|
@@ -9,6 +9,7 @@ export declare const search: import("@orpc/contract").ContractProcedureBuilderWi
|
|
|
9
9
|
eric: "eric";
|
|
10
10
|
"europe-pmc": "europe-pmc";
|
|
11
11
|
openalex: "openalex";
|
|
12
|
+
crossref: "crossref";
|
|
12
13
|
}>>>;
|
|
13
14
|
offset: z.ZodDefault<z.ZodNumber>;
|
|
14
15
|
limit: z.ZodDefault<z.ZodNumber>;
|
|
@@ -58,6 +59,7 @@ export declare const search: import("@orpc/contract").ContractProcedureBuilderWi
|
|
|
58
59
|
eric: "eric";
|
|
59
60
|
"europe-pmc": "europe-pmc";
|
|
60
61
|
openalex: "openalex";
|
|
62
|
+
crossref: "crossref";
|
|
61
63
|
}>>>;
|
|
62
64
|
providerData: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
63
65
|
}, z.core.$strip>>;
|
|
@@ -8,8 +8,9 @@ const providerSchema = z.enum([
|
|
|
8
8
|
"eric",
|
|
9
9
|
"europe-pmc",
|
|
10
10
|
"openalex",
|
|
11
|
+
"crossref",
|
|
11
12
|
], {
|
|
12
|
-
message: "Invalid provider. Must be one of: semantic-scholar, pubmed, arxiv, google-scholar, eric, europe-pmc, openalex",
|
|
13
|
+
message: "Invalid provider. Must be one of: semantic-scholar, pubmed, arxiv, google-scholar, eric, europe-pmc, openalex, crossref",
|
|
13
14
|
});
|
|
14
15
|
const authorSchema = z.object({
|
|
15
16
|
name: z.string(),
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const similarPapers: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
includeEdges: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
fields: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodEnum<{
|
|
7
|
+
url: "url";
|
|
8
|
+
doi: "doi";
|
|
9
|
+
title: "title";
|
|
10
|
+
providerURL: "providerURL";
|
|
11
|
+
date: "date";
|
|
12
|
+
authors: "authors";
|
|
13
|
+
year: "year";
|
|
14
|
+
totalCitations: "totalCitations";
|
|
15
|
+
totalReferences: "totalReferences";
|
|
16
|
+
abstract: "abstract";
|
|
17
|
+
pdfURL: "pdfURL";
|
|
18
|
+
provider: "provider";
|
|
19
|
+
providerData: "providerData";
|
|
20
|
+
}>>>>;
|
|
21
|
+
callback: z.ZodOptional<z.ZodObject<{
|
|
22
|
+
url: z.ZodURL;
|
|
23
|
+
type: z.ZodOptional<z.ZodString>;
|
|
24
|
+
}, z.core.$strip>>;
|
|
25
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
26
|
+
seed: z.ZodObject<{
|
|
27
|
+
doi: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
28
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
29
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
30
|
+
providerURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
31
|
+
authors: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
32
|
+
name: z.ZodString;
|
|
33
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
34
|
+
}, z.core.$strip>>>>;
|
|
35
|
+
date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
36
|
+
year: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
37
|
+
totalCitations: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
38
|
+
totalReferences: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
39
|
+
abstract: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
40
|
+
pdfURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
41
|
+
provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
42
|
+
providerData: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
results: z.ZodArray<z.ZodObject<{
|
|
45
|
+
publication: z.ZodObject<{
|
|
46
|
+
doi: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
47
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
48
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
49
|
+
providerURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
50
|
+
authors: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
51
|
+
name: z.ZodString;
|
|
52
|
+
url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
53
|
+
}, z.core.$strip>>>>;
|
|
54
|
+
date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
55
|
+
year: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
56
|
+
totalCitations: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
57
|
+
totalReferences: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
58
|
+
abstract: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
59
|
+
pdfURL: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
60
|
+
provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
61
|
+
providerData: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
62
|
+
}, z.core.$strip>;
|
|
63
|
+
similarity: z.ZodNumber;
|
|
64
|
+
pageRank: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
65
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
66
|
+
citingIds: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
67
|
+
citedByIds: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
68
|
+
}, z.core.$strip>>;
|
|
69
|
+
requestId: z.ZodNumber;
|
|
70
|
+
}, z.core.$strip>, Record<never, never>, Record<never, never>>;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const authorSchema = z.object({
|
|
4
|
+
name: z.string(),
|
|
5
|
+
url: z.string().nullish(),
|
|
6
|
+
});
|
|
7
|
+
const publicationSchema = z.object({
|
|
8
|
+
doi: z.string().nullish(),
|
|
9
|
+
title: z.string().nullish(),
|
|
10
|
+
url: z.string().nullish(),
|
|
11
|
+
providerURL: z.string().nullish(),
|
|
12
|
+
authors: z.array(authorSchema).nullish(),
|
|
13
|
+
date: z.string().nullish(),
|
|
14
|
+
year: z.number().nullish(),
|
|
15
|
+
totalCitations: z.number().nullish(),
|
|
16
|
+
totalReferences: z.number().nullish(),
|
|
17
|
+
abstract: z.string().nullish(),
|
|
18
|
+
pdfURL: z.string().nullish(),
|
|
19
|
+
provider: z.string().nullish(),
|
|
20
|
+
providerData: z.record(z.string(), z.unknown()).nullish(),
|
|
21
|
+
});
|
|
22
|
+
const similarPaperSchema = z.object({
|
|
23
|
+
publication: publicationSchema,
|
|
24
|
+
similarity: z
|
|
25
|
+
.number()
|
|
26
|
+
.describe("Combined similarity score from citation network analysis"),
|
|
27
|
+
pageRank: z.number().nullish().describe("Citation network importance score"),
|
|
28
|
+
distance: z
|
|
29
|
+
.number()
|
|
30
|
+
.int()
|
|
31
|
+
.nullish()
|
|
32
|
+
.describe("Graph distance from seed paper"),
|
|
33
|
+
citingIds: z
|
|
34
|
+
.array(z.string())
|
|
35
|
+
.nullish()
|
|
36
|
+
.describe("OpenAlex IDs of papers in result set that cite this paper (only if includeEdges=true)"),
|
|
37
|
+
citedByIds: z
|
|
38
|
+
.array(z.string())
|
|
39
|
+
.nullish()
|
|
40
|
+
.describe("OpenAlex IDs of papers in result set cited by this paper (only if includeEdges=true)"),
|
|
41
|
+
});
|
|
42
|
+
const requestExamples = {
|
|
43
|
+
"Find similar papers by DOI": {
|
|
44
|
+
summary: "Find papers similar to a given paper",
|
|
45
|
+
value: {
|
|
46
|
+
id: "10.1038/nature12373",
|
|
47
|
+
limit: 20,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
"Find similar with edges": {
|
|
51
|
+
summary: "Find similar papers with citation graph edges",
|
|
52
|
+
value: {
|
|
53
|
+
id: "10.1038/nature12373",
|
|
54
|
+
limit: 20,
|
|
55
|
+
includeEdges: true,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
"Find similar by OpenAlex ID": {
|
|
59
|
+
summary: "Find similar papers using an OpenAlex ID",
|
|
60
|
+
value: {
|
|
61
|
+
id: "W2963403868",
|
|
62
|
+
limit: 10,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
export const similarPapers = oc
|
|
67
|
+
.input(z.object({
|
|
68
|
+
id: z
|
|
69
|
+
.string({ message: "id is required and must be a string" })
|
|
70
|
+
.min(1, "id must not be empty")
|
|
71
|
+
.max(500, "id must be at most 500 characters")
|
|
72
|
+
.describe("Seed paper identifier. Supports DOI, Semantic Scholar ID, ArXiv ID, PubMed ID, OpenAlex ID, or URL."),
|
|
73
|
+
limit: z
|
|
74
|
+
.number({ message: "limit must be a number" })
|
|
75
|
+
.int("limit must be a whole number")
|
|
76
|
+
.min(1, "limit must be at least 1")
|
|
77
|
+
.max(100, "limit must be at most 100")
|
|
78
|
+
.default(30)
|
|
79
|
+
.describe("Maximum number of similar papers to return"),
|
|
80
|
+
includeEdges: z
|
|
81
|
+
.boolean({ message: "includeEdges must be a boolean" })
|
|
82
|
+
.default(false)
|
|
83
|
+
.describe("Whether to include citing/cited_by edge data for graph construction"),
|
|
84
|
+
fields: z
|
|
85
|
+
.array(z.enum([
|
|
86
|
+
"doi",
|
|
87
|
+
"title",
|
|
88
|
+
"url",
|
|
89
|
+
"providerURL",
|
|
90
|
+
"authors",
|
|
91
|
+
"date",
|
|
92
|
+
"year",
|
|
93
|
+
"totalCitations",
|
|
94
|
+
"totalReferences",
|
|
95
|
+
"abstract",
|
|
96
|
+
"pdfURL",
|
|
97
|
+
"provider",
|
|
98
|
+
"providerData",
|
|
99
|
+
]), {
|
|
100
|
+
message: "fields must be an array of valid publication field names",
|
|
101
|
+
})
|
|
102
|
+
.nullish()
|
|
103
|
+
.describe("Specific publication fields to return. If omitted, returns all fields except providerData."),
|
|
104
|
+
callback: z
|
|
105
|
+
.object({
|
|
106
|
+
url: z
|
|
107
|
+
.url()
|
|
108
|
+
.describe("Webhook URL where results will be POSTed when processing completes"),
|
|
109
|
+
type: z
|
|
110
|
+
.string()
|
|
111
|
+
.optional()
|
|
112
|
+
.describe("Callback type identifier (e.g. 'zapier')"),
|
|
113
|
+
})
|
|
114
|
+
.optional()
|
|
115
|
+
.describe("Optional webhook callback for async processing. " +
|
|
116
|
+
"When provided, the server returns 202 immediately and POSTs the full response payload to the callback URL when processing completes. " +
|
|
117
|
+
"On error, the callback receives a POST with X-Pdfvector-Callback-Failed: true header and error details in the body. " +
|
|
118
|
+
"Useful for long-running operations that may exceed client timeout limits."),
|
|
119
|
+
}))
|
|
120
|
+
.output(z.object({
|
|
121
|
+
seed: publicationSchema,
|
|
122
|
+
results: z.array(similarPaperSchema),
|
|
123
|
+
requestId: z.number().int(),
|
|
124
|
+
}))
|
|
125
|
+
.route({
|
|
126
|
+
summary: "Find similar papers",
|
|
127
|
+
description: "Find papers similar to a seed paper using citation network analysis. Returns papers ranked by similarity with optional graph edge data for visualization.",
|
|
128
|
+
tags: ["Academic"],
|
|
129
|
+
spec: (op) => {
|
|
130
|
+
op.security = [{ bearerAuth: [] }];
|
|
131
|
+
const reqBody = op.requestBody;
|
|
132
|
+
if (reqBody?.content) {
|
|
133
|
+
for (const mediaType of Object.values(reqBody.content)) {
|
|
134
|
+
mediaType.examples = requestExamples;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return op;
|
|
138
|
+
},
|
|
139
|
+
});
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @pdfvector/instance-contract
|
|
2
2
|
|
|
3
|
+
## 0.0.30
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
- [#150](https://github.com/phuctm97/pdfvector/pull/150) [`aaf8ba1`](https://github.com/phuctm97/pdfvector/commit/aaf8ba1a73c4076cc63c17fcd47e463b05d7db2a) Thanks [@khanhduyvt0101](https://github.com/khanhduyvt0101)! - Add grant search API and remove unused academic providers
|
|
9
|
+
|
|
10
|
+
## 0.0.29
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
- [#149](https://github.com/phuctm97/pdfvector/pull/149) [`bcffa28`](https://github.com/phuctm97/pdfvector/commit/bcffa2840c98af3e8ab0c971e61d580beedd3b85) Thanks [@khanhduyvt0101](https://github.com/khanhduyvt0101)! - Add academic paper graph and similar papers APIs with integration tests
|
|
16
|
+
|
|
3
17
|
## 0.0.28
|
|
4
18
|
### Patch Changes
|
|
5
19
|
|