@inflexa-ai/harness 0.30.3 → 0.31.1
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/contracts/target-dossier.d.ts +61 -61
- package/dist/execution/run-synthesis.js +7 -2
- package/dist/lib/zod-issues.d.ts +8 -0
- package/dist/lib/zod-issues.js +13 -0
- package/dist/literature/sources/semantic-scholar.d.ts +34 -0
- package/dist/literature/sources/semantic-scholar.js +15 -4
- package/dist/prompts/briefing.d.ts +12 -1
- package/dist/prompts/briefing.js +27 -1
- package/dist/prompts/sandbox-standards.d.ts +1 -1
- package/dist/prompts/sandbox-standards.js +27 -0
- package/dist/sandbox/thread-env.d.ts +18 -12
- package/dist/sandbox/thread-env.js +36 -25
- package/dist/tools/bio/chembl.js +4 -3
- package/dist/tools/bio/drug-gene-interactions.d.ts +2 -14
- package/dist/tools/bio/drug-gene-interactions.js +10 -18
- package/dist/tools/bio/gene-disease-evidence.d.ts +3 -1
- package/dist/tools/bio/gene-disease-evidence.js +12 -9
- package/dist/tools/bio/keys.js +1 -0
- package/dist/tools/bio/lookup-annotation.d.ts +43 -0
- package/dist/tools/bio/lookup-annotation.js +19 -4
- package/dist/tools/bio/pubchem.js +5 -3
- package/dist/tools/bio/search-clinical-trials.js +5 -4
- package/dist/tools/bio/search-geo-datasets.d.ts +39 -9
- package/dist/tools/bio/search-geo-datasets.js +38 -20
- package/dist/tools/lib/api-utils.d.ts +27 -2
- package/dist/tools/lib/api-utils.js +43 -3
- package/dist/tools/lib/bgee-client.d.ts +16 -0
- package/dist/tools/lib/bgee-client.js +16 -5
- package/dist/tools/lib/cbioportal-client.d.ts +20 -0
- package/dist/tools/lib/cbioportal-client.js +16 -8
- package/dist/tools/lib/chembl-client.d.ts +105 -3
- package/dist/tools/lib/chembl-client.js +196 -84
- package/dist/tools/lib/clinical-benchmarks-client.d.ts +5 -0
- package/dist/tools/lib/clinical-benchmarks-client.js +5 -0
- package/dist/tools/lib/clinical-trials-client.d.ts +131 -2
- package/dist/tools/lib/clinical-trials-client.js +32 -6
- package/dist/tools/lib/clinvar-client.d.ts +35 -0
- package/dist/tools/lib/clinvar-client.js +34 -28
- package/dist/tools/lib/ctx-ops.d.ts +106 -35
- package/dist/tools/lib/ctx-ops.js +135 -69
- package/dist/tools/lib/dgidb-client.d.ts +73 -0
- package/dist/tools/lib/dgidb-client.js +25 -13
- package/dist/tools/lib/disgenet-client.d.ts +117 -24
- package/dist/tools/lib/disgenet-client.js +127 -34
- package/dist/tools/lib/disgenet-config.d.ts +1 -1
- package/dist/tools/lib/disgenet-config.js +5 -3
- package/dist/tools/lib/drugbank-client.d.ts +57 -58
- package/dist/tools/lib/drugbank-client.js +69 -64
- package/dist/tools/lib/drugbank-config.d.ts +6 -1
- package/dist/tools/lib/drugbank-config.js +6 -1
- package/dist/tools/lib/ema-client.d.ts +53 -0
- package/dist/tools/lib/ema-client.js +19 -7
- package/dist/tools/lib/ensembl-client.d.ts +4 -0
- package/dist/tools/lib/ensembl-client.js +4 -0
- package/dist/tools/lib/gwas-catalog-client.d.ts +64 -1
- package/dist/tools/lib/gwas-catalog-client.js +21 -6
- package/dist/tools/lib/identifier-resolver.d.ts +17 -1
- package/dist/tools/lib/identifier-resolver.js +13 -4
- package/dist/tools/lib/impc-client.d.ts +4 -0
- package/dist/tools/lib/impc-client.js +4 -0
- package/dist/tools/lib/iuphar-client.d.ts +10 -5
- package/dist/tools/lib/iuphar-client.js +49 -13
- package/dist/tools/lib/monarch-client.d.ts +4 -0
- package/dist/tools/lib/monarch-client.js +4 -0
- package/dist/tools/lib/openfda-client.d.ts +34 -0
- package/dist/tools/lib/openfda-client.js +22 -8
- package/dist/tools/lib/opentargets-client.d.ts +99 -4
- package/dist/tools/lib/opentargets-client.js +97 -37
- package/dist/tools/lib/pathway-client.d.ts +45 -0
- package/dist/tools/lib/pathway-client.js +88 -8
- package/dist/tools/lib/pharmgkb-client.d.ts +35 -1
- package/dist/tools/lib/pharmgkb-client.js +22 -6
- package/dist/tools/lib/pharmgkb-config.d.ts +8 -1
- package/dist/tools/lib/pharmgkb-config.js +8 -1
- package/dist/tools/lib/pubchem-client.d.ts +22 -0
- package/dist/tools/lib/pubchem-client.js +36 -33
- package/dist/tools/lib/pubchem-ops.d.ts +85 -5
- package/dist/tools/lib/pubchem-ops.js +96 -68
- package/dist/tools/lib/pubmed-client.d.ts +4 -0
- package/dist/tools/lib/pubmed-client.js +4 -0
- package/dist/tools/lib/string-client.d.ts +52 -0
- package/dist/tools/lib/string-client.js +12 -7
- package/dist/tools/lib/uniprot-client.d.ts +4 -0
- package/dist/tools/lib/uniprot-client.js +4 -0
- package/dist/tools/research/context7-docs.d.ts +23 -0
- package/dist/tools/research/context7-docs.js +49 -9
- package/dist/tools/research/search-github-repos.d.ts +4 -0
- package/dist/tools/research/search-github-repos.js +4 -0
- package/dist/workflows/execute-target-assessment.js +4 -4
- package/dist/workflows/target-assessment/assemblers/orchestrator.d.ts +2 -1
- package/dist/workflows/target-assessment/assemblers/orchestrator.js +3 -3
- package/dist/workflows/target-assessment/collectors/index.d.ts +8 -2
- package/dist/workflows/target-assessment/collectors/index.js +37 -10
- package/dist/workflows/target-assessment/fanout/index.d.ts +2 -1
- package/dist/workflows/target-assessment/fanout/index.js +2 -2
- package/dist/workflows/target-assessment/lib/safety-corroboration.js +2 -2
- package/dist/workflows/target-assessment/lib/target-identity-filter.d.ts +3 -2
- package/dist/workflows/target-assessment/lib/target-identity-filter.js +16 -5
- package/dist/workflows/target-assessment/phase4-assemble.d.ts +61 -60
- package/dist/workflows/target-assessment/phase4-assemble.js +2 -2
- package/dist/workflows/target-assessment/schemas.d.ts +2 -8
- package/dist/workflows/target-assessment/schemas.js +8 -2
- package/dist/workflows/target-assessment/steps/phase2-aggregate.d.ts +1 -4
- package/dist/workflows/target-assessment/steps/phase3-aggregate.d.ts +1 -4
- package/package.json +1 -1
- package/dist/agents/sandbox/__fixtures__/deps.d.ts +0 -23
- package/dist/agents/sandbox/__fixtures__/deps.js +0 -102
- package/dist/citations/__fixtures__/resolver.d.ts +0 -3
- package/dist/citations/__fixtures__/resolver.js +0 -9
- package/dist/loop/__fixtures__/scripted-provider.d.ts +0 -31
- package/dist/loop/__fixtures__/scripted-provider.js +0 -81
- package/dist/providers/__fixtures__/session.d.ts +0 -17
- package/dist/providers/__fixtures__/session.js +0 -20
- package/dist/tools/__fixtures__/tool-context.d.ts +0 -13
- package/dist/tools/__fixtures__/tool-context.js +0 -22
|
@@ -1,91 +1,96 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pure async client functions for DrugBank.
|
|
2
|
+
* Pure async client functions for the DrugBank Discovery API.
|
|
3
|
+
*
|
|
4
|
+
* CONTRACT UNVERIFIED (key-blocked, 2026-08-28). No key exists here, and an
|
|
5
|
+
* unauthenticated probe answers 401 before it routes, thus no live call proves
|
|
6
|
+
* a route or a record. The evidence is secondary: the Wayback captures of
|
|
7
|
+
* `docs.drugbank.com/discovery/v1` and the sample code of the provider. Refer to
|
|
8
|
+
* the truth map, file 07, section 1.
|
|
3
9
|
*
|
|
4
10
|
* Requires a DrugBank API key; `getDrugbankHeaders` throws when it is absent.
|
|
11
|
+
*
|
|
12
|
+
* Absence policy: no evidence establishes the encoding of an absent value,
|
|
13
|
+
* because no key exists for a live call and both fixtures are synthetic. Each
|
|
14
|
+
* maybe-absent field carries `.optional()` today, and no field carries
|
|
15
|
+
* `.nullable()`.
|
|
5
16
|
*/
|
|
6
17
|
import { z } from "zod";
|
|
7
18
|
import { apiFetchValidated, describeApiError } from "./api-utils.js";
|
|
8
19
|
import { DRUGBANK_BASE, getDrugbankHeaders } from "./drugbank-config.js";
|
|
9
20
|
/** Hard ceiling on each prose field at the parse boundary; callers trim further. */
|
|
10
21
|
const PROSE_CEILING = 500;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
// rejected as `invalid_response` instead of being silently
|
|
18
|
-
// the schema carries the transform, `z.infer` below is the
|
|
19
|
-
// type callers receive
|
|
20
|
-
//
|
|
22
|
+
/** The page ceiling of the `per_page` parameter. There is no `limit` parameter. */
|
|
23
|
+
const MAX_PER_PAGE = 50;
|
|
24
|
+
// A single schema that both validates and normalizes one Discovery drug record.
|
|
25
|
+
// The `.object(...)` half is the snake_case wire shape; the `.transform(...)`
|
|
26
|
+
// half maps it into the camelCase result we return. Parsing IS the validation:
|
|
27
|
+
// `apiFetchValidated` runs this schema over the JSON, so a payload whose field
|
|
28
|
+
// TYPES drift is rejected as `invalid_response` instead of being silently
|
|
29
|
+
// mis-mapped. Because the schema carries the transform, `z.infer` below is the
|
|
30
|
+
// OUTPUT (camelCase) type callers receive.
|
|
31
|
+
//
|
|
32
|
+
// `drugbank_id` is MANDATORY. It is the one key that every Discovery record
|
|
33
|
+
// carries, thus an error envelope such as `{"error":"Key invalid"}` fails the
|
|
34
|
+
// parse and the caller sees `invalid_response` rather than one blank drug row.
|
|
21
35
|
const DrugResultSchema = z
|
|
22
36
|
.object({
|
|
23
|
-
drugbank_id: z.string()
|
|
37
|
+
drugbank_id: z.string(),
|
|
24
38
|
name: z.string().optional(),
|
|
25
39
|
description: z.string().optional(),
|
|
26
40
|
type: z.string().optional(),
|
|
27
41
|
groups: z.array(z.string()).optional(),
|
|
28
|
-
categories: z.array(z.object({ category: z.string().optional() })).optional(),
|
|
29
|
-
indication: z.string().optional(),
|
|
30
|
-
pharmacodynamics: z.string().optional(),
|
|
31
|
-
mechanism_of_action: z.string().optional(),
|
|
32
|
-
toxicity: z.string().optional(),
|
|
33
|
-
half_life: z.string().optional(),
|
|
34
|
-
targets: z
|
|
35
|
-
.array(z.object({
|
|
36
|
-
name: z.string().optional(),
|
|
37
|
-
gene_name: z.string().optional(),
|
|
38
|
-
actions: z.array(z.string()).optional(),
|
|
39
|
-
known_action: z.string().optional(),
|
|
40
|
-
}))
|
|
41
|
-
.optional(),
|
|
42
|
-
drug_interactions: z
|
|
43
|
-
.array(z.object({
|
|
44
|
-
drugbank_id: z.string().optional(),
|
|
45
|
-
name: z.string().optional(),
|
|
46
|
-
description: z.string().optional(),
|
|
47
|
-
}))
|
|
48
|
-
.optional(),
|
|
49
42
|
})
|
|
50
43
|
.transform((raw) => ({
|
|
51
|
-
drugbankId: raw.drugbank_id
|
|
44
|
+
drugbankId: raw.drugbank_id,
|
|
52
45
|
name: raw.name ?? "",
|
|
53
46
|
description: (raw.description ?? "").slice(0, PROSE_CEILING),
|
|
54
47
|
type: raw.type ?? "",
|
|
55
48
|
groups: raw.groups ?? [],
|
|
56
|
-
categories: (raw.categories ?? []).map((c) => c.category ?? "").filter(Boolean),
|
|
57
|
-
indication: (raw.indication ?? "").slice(0, PROSE_CEILING),
|
|
58
|
-
pharmacodynamics: (raw.pharmacodynamics ?? "").slice(0, PROSE_CEILING),
|
|
59
|
-
mechanismOfAction: (raw.mechanism_of_action ?? "").slice(0, PROSE_CEILING),
|
|
60
|
-
toxicity: (raw.toxicity ?? "").slice(0, PROSE_CEILING),
|
|
61
|
-
halfLife: raw.half_life ?? "",
|
|
62
|
-
targets: (raw.targets ?? []).map((t) => ({
|
|
63
|
-
name: t.name ?? "",
|
|
64
|
-
geneSymbol: t.gene_name ?? "",
|
|
65
|
-
actions: t.actions ?? [],
|
|
66
|
-
knownAction: t.known_action ?? "",
|
|
67
|
-
})),
|
|
68
|
-
interactions: (raw.drug_interactions ?? []).map((i) => ({
|
|
69
|
-
drugbankId: i.drugbank_id ?? "",
|
|
70
|
-
name: i.name ?? "",
|
|
71
|
-
description: (i.description ?? "").slice(0, 200),
|
|
72
|
-
})),
|
|
73
49
|
}));
|
|
74
|
-
// The
|
|
75
|
-
//
|
|
76
|
-
|
|
50
|
+
// The Discovery API wraps nothing: a list route answers with a bare JSON array,
|
|
51
|
+
// and a lookup route answers with a bare object. Accept either, and transform
|
|
52
|
+
// each element.
|
|
53
|
+
export const DrugResponseSchema = z.union([DrugResultSchema, z.array(DrugResultSchema)]);
|
|
54
|
+
// One bond of `/bonds/targets`. The row names the drug that binds the target,
|
|
55
|
+
// thus a gene query reaches the drugs through the bonds. The bond carries no
|
|
56
|
+
// drug record beyond the id and the name.
|
|
57
|
+
export const BondResponseSchema = z.array(z.object({
|
|
58
|
+
drug: z.object({ drugbank_id: z.string(), name: z.string().optional() }),
|
|
59
|
+
}));
|
|
60
|
+
/** Translate the internal limit into the `per_page` of the provider. */
|
|
61
|
+
function perPageOf(limit) {
|
|
62
|
+
return Math.min(Math.max(limit, 1), MAX_PER_PAGE);
|
|
63
|
+
}
|
|
64
|
+
/** The drugs that bind a target, keyed by the gene name of its polypeptides. */
|
|
65
|
+
async function searchDrugbankByTarget(headers, gene, limit) {
|
|
66
|
+
const query = encodeURIComponent(`polypeptides.gene_name:${gene}`);
|
|
67
|
+
const url = `${DRUGBANK_BASE}/bonds/targets?q=${query}&per_page=${perPageOf(limit)}`;
|
|
68
|
+
const res = await apiFetchValidated(url, BondResponseSchema, { headers });
|
|
69
|
+
if (res.isErr())
|
|
70
|
+
throw new Error(describeApiError(res.error));
|
|
71
|
+
// One drug binds a target through more than one bond, thus the rows repeat a
|
|
72
|
+
// drug. The map keeps the first row of each drug.
|
|
73
|
+
const drugs = new Map();
|
|
74
|
+
for (const bond of res.value) {
|
|
75
|
+
if (drugs.has(bond.drug.drugbank_id))
|
|
76
|
+
continue;
|
|
77
|
+
drugs.set(bond.drug.drugbank_id, {
|
|
78
|
+
drugbankId: bond.drug.drugbank_id,
|
|
79
|
+
name: bond.drug.name ?? "",
|
|
80
|
+
description: "",
|
|
81
|
+
type: "",
|
|
82
|
+
groups: [],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return [...drugs.values()].slice(0, limit);
|
|
86
|
+
}
|
|
77
87
|
export async function searchDrugbank(apiKey, query, searchType, limit = 10) {
|
|
78
88
|
const headers = getDrugbankHeaders(apiKey);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
url = `${DRUGBANK_BASE}/drugs/${query}`;
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
url = `${DRUGBANK_BASE}/drugs?q=${encodeURIComponent(query)}&limit=${limit}`;
|
|
88
|
-
}
|
|
89
|
+
if (searchType === "target")
|
|
90
|
+
return searchDrugbankByTarget(headers, query, limit);
|
|
91
|
+
const url = query.startsWith("DB")
|
|
92
|
+
? `${DRUGBANK_BASE}/drugs/${encodeURIComponent(query)}`
|
|
93
|
+
: `${DRUGBANK_BASE}/drugs?q=${encodeURIComponent(query)}&per_page=${perPageOf(limit)}`;
|
|
89
94
|
const res = await apiFetchValidated(url, DrugResponseSchema, { headers });
|
|
90
95
|
if (res.isErr())
|
|
91
96
|
throw new Error(describeApiError(res.error));
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The Discovery API of DrugBank. The Clinical API (`/v1`) serves no `?q=` search
|
|
3
|
+
* on its drug resource, thus only Discovery answers a name search and a target
|
|
4
|
+
* search.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DRUGBANK_BASE = "https://api.drugbank.com/discovery/v1";
|
|
2
7
|
export declare function getDrugbankHeaders(apiKey: string): Record<string, string>;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The Discovery API of DrugBank. The Clinical API (`/v1`) serves no `?q=` search
|
|
3
|
+
* on its drug resource, thus only Discovery answers a name search and a target
|
|
4
|
+
* search.
|
|
5
|
+
*/
|
|
6
|
+
export const DRUGBANK_BASE = "https://api.drugbank.com/discovery/v1";
|
|
2
7
|
export function getDrugbankHeaders(apiKey) {
|
|
3
8
|
const key = apiKey;
|
|
4
9
|
if (!key) {
|
|
@@ -7,7 +7,12 @@
|
|
|
7
7
|
* Article 20, etc.). We fetch and cache it in-process; per-drug queries
|
|
8
8
|
* filter the cached records by INN, referral name, and associated
|
|
9
9
|
* medicine names.
|
|
10
|
+
*
|
|
11
|
+
* Absence policy: the bulk file gives each key and writes an absent value as
|
|
12
|
+
* the empty string. Thus a field carries neither `.nullable()` nor
|
|
13
|
+
* `.optional()`.
|
|
10
14
|
*/
|
|
15
|
+
import { z } from "zod";
|
|
11
16
|
export interface EmaReferral {
|
|
12
17
|
category: string;
|
|
13
18
|
referralName: string;
|
|
@@ -29,6 +34,54 @@ export interface EmaReferral {
|
|
|
29
34
|
lastUpdatedDate: string;
|
|
30
35
|
referralUrl: string;
|
|
31
36
|
}
|
|
37
|
+
/** The catalogue file. It is exported so that the golden-fixture table drives it. */
|
|
38
|
+
export declare const ReferralFileSchema: z.ZodObject<{
|
|
39
|
+
meta: z.ZodOptional<z.ZodObject<{
|
|
40
|
+
total_records: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
timestamp: z.ZodOptional<z.ZodString>;
|
|
42
|
+
}, z.core.$strip>>;
|
|
43
|
+
data: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodObject<{
|
|
44
|
+
category: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
45
|
+
referral_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
46
|
+
international_non_proprietary_name_inn_common_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
47
|
+
current_status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
48
|
+
safety_referral: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
49
|
+
referral_type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
50
|
+
associated_names_centrally_authorised_medicines: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
51
|
+
associated_names_non_centrally_authorised_medicines: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
52
|
+
class: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
53
|
+
reference_number: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
54
|
+
authorisation_model: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
55
|
+
procedure_start_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
56
|
+
prac_recommendation_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
57
|
+
cmdh_position_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
58
|
+
chmp_cvmp_opinion_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
59
|
+
european_commission_decision_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
60
|
+
first_published_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
61
|
+
last_updated_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
62
|
+
referral_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
63
|
+
}, z.core.$strip>, z.ZodTransform<EmaReferral, {
|
|
64
|
+
category?: string | null | undefined;
|
|
65
|
+
referral_name?: string | null | undefined;
|
|
66
|
+
international_non_proprietary_name_inn_common_name?: string | null | undefined;
|
|
67
|
+
current_status?: string | null | undefined;
|
|
68
|
+
safety_referral?: string | null | undefined;
|
|
69
|
+
referral_type?: string | null | undefined;
|
|
70
|
+
associated_names_centrally_authorised_medicines?: string | null | undefined;
|
|
71
|
+
associated_names_non_centrally_authorised_medicines?: string | null | undefined;
|
|
72
|
+
class?: string | null | undefined;
|
|
73
|
+
reference_number?: string | null | undefined;
|
|
74
|
+
authorisation_model?: string | null | undefined;
|
|
75
|
+
procedure_start_date?: string | null | undefined;
|
|
76
|
+
prac_recommendation_date?: string | null | undefined;
|
|
77
|
+
cmdh_position_date?: string | null | undefined;
|
|
78
|
+
chmp_cvmp_opinion_date?: string | null | undefined;
|
|
79
|
+
european_commission_decision_date?: string | null | undefined;
|
|
80
|
+
first_published_date?: string | null | undefined;
|
|
81
|
+
last_updated_date?: string | null | undefined;
|
|
82
|
+
referral_url?: string | null | undefined;
|
|
83
|
+
}>>>>;
|
|
84
|
+
}, z.core.$strip>;
|
|
32
85
|
/**
|
|
33
86
|
* Download (or return cached) full EMA referrals catalogue. The catalogue
|
|
34
87
|
* updates twice daily — a 6h in-process TTL is well within freshness
|
|
@@ -7,26 +7,37 @@
|
|
|
7
7
|
* Article 20, etc.). We fetch and cache it in-process; per-drug queries
|
|
8
8
|
* filter the cached records by INN, referral name, and associated
|
|
9
9
|
* medicine names.
|
|
10
|
+
*
|
|
11
|
+
* Absence policy: the bulk file gives each key and writes an absent value as
|
|
12
|
+
* the empty string. Thus a field carries neither `.nullable()` nor
|
|
13
|
+
* `.optional()`.
|
|
10
14
|
*/
|
|
11
15
|
import { z } from "zod";
|
|
12
16
|
import { apiFetchValidated, describeApiError } from "./api-utils.js";
|
|
13
17
|
import { EMA_REFERRALS_URL } from "./ema-config.js";
|
|
18
|
+
/**
|
|
19
|
+
* Split one medicine column into names.
|
|
20
|
+
*
|
|
21
|
+
* The separator is the semicolon alone. A comma belongs to the name of the
|
|
22
|
+
* medicine, for example `Lidocaïne / Prilocaïne 5% Focus, Crème`, thus a split on
|
|
23
|
+
* the comma breaks that name into two.
|
|
24
|
+
*/
|
|
14
25
|
function parseMedicineList(field) {
|
|
15
26
|
if (!field || !field.trim())
|
|
16
27
|
return [];
|
|
17
28
|
return field
|
|
18
|
-
.split(
|
|
29
|
+
.split(";")
|
|
19
30
|
.map((s) => s.trim())
|
|
20
31
|
.filter(Boolean);
|
|
21
32
|
}
|
|
22
|
-
// One schema that both validates the raw referral wire shape (snake_case
|
|
23
|
-
// field optional or null — the bulk file omits or nulls absent values) and
|
|
33
|
+
// One schema that both validates the raw referral wire shape (snake_case) and
|
|
24
34
|
// normalizes it into the camelCase `EmaReferral` we return. Parsing IS the
|
|
25
35
|
// validation: `apiFetchValidated` runs this over the download, so a record whose
|
|
26
36
|
// field TYPES drift is rejected as `invalid_response` instead of silently
|
|
27
|
-
// mis-mapped.
|
|
28
|
-
//
|
|
29
|
-
//
|
|
37
|
+
// mis-mapped. The sampled records give each key and write an absent value as the
|
|
38
|
+
// empty string. The modifiers stay wider than that sample, thus one odd record in
|
|
39
|
+
// the ~600-row catalogue does not fail the whole `data` array. The transform
|
|
40
|
+
// collapses a null to "" with `??`.
|
|
30
41
|
const EmaReferralSchema = z
|
|
31
42
|
.object({
|
|
32
43
|
category: z.string().nullable().optional(),
|
|
@@ -70,7 +81,8 @@ const EmaReferralSchema = z
|
|
|
70
81
|
lastUpdatedDate: raw.last_updated_date ?? "",
|
|
71
82
|
referralUrl: raw.referral_url ?? "",
|
|
72
83
|
}));
|
|
73
|
-
|
|
84
|
+
/** The catalogue file. It is exported so that the golden-fixture table drives it. */
|
|
85
|
+
export const ReferralFileSchema = z.object({
|
|
74
86
|
meta: z.object({ total_records: z.number().optional(), timestamp: z.string().optional() }).optional(),
|
|
75
87
|
data: z.array(EmaReferralSchema).optional(),
|
|
76
88
|
});
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Pure async client functions for the Ensembl REST API.
|
|
3
3
|
*
|
|
4
4
|
* Used by §1.1 (Entity resolution) and as a fallback for ID resolution.
|
|
5
|
+
*
|
|
6
|
+
* Absence policy: Ensembl omits the key of an absent value, and it never sends
|
|
7
|
+
* an explicit `null`. Thus a maybe-absent field carries `.optional()`, not
|
|
8
|
+
* `.nullable()`.
|
|
5
9
|
*/
|
|
6
10
|
export interface GeneInfo {
|
|
7
11
|
symbol: string;
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Pure async client functions for the Ensembl REST API.
|
|
3
3
|
*
|
|
4
4
|
* Used by §1.1 (Entity resolution) and as a fallback for ID resolution.
|
|
5
|
+
*
|
|
6
|
+
* Absence policy: Ensembl omits the key of an absent value, and it never sends
|
|
7
|
+
* an explicit `null`. Thus a maybe-absent field carries `.optional()`, not
|
|
8
|
+
* `.nullable()`.
|
|
5
9
|
*/
|
|
6
10
|
import { z } from "zod";
|
|
7
11
|
import { apiFetchValidated, describeApiError } from "./api-utils.js";
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
* per-SNP associations), by trait (EFO trait search then its associations), by
|
|
6
6
|
* variant (direct rsID associations), and by study (the associations of one
|
|
7
7
|
* GCST study accession).
|
|
8
|
+
*
|
|
9
|
+
* Absence policy: the sampled payloads show an explicit `null` for an absent
|
|
10
|
+
* leaf value, and the key set of one projection stays constant. A key is absent
|
|
11
|
+
* only when the projection that the request named excludes it.
|
|
8
12
|
*/
|
|
9
13
|
import { z } from "zod";
|
|
10
14
|
export interface GwasAssociation {
|
|
@@ -38,7 +42,9 @@ declare const RawGwasAssociationSchema: z.ZodObject<{
|
|
|
38
42
|
}, z.core.$strip>>>;
|
|
39
43
|
study: z.ZodOptional<z.ZodObject<{
|
|
40
44
|
accessionId: z.ZodOptional<z.ZodString>;
|
|
41
|
-
|
|
45
|
+
publicationInfo: z.ZodOptional<z.ZodObject<{
|
|
46
|
+
pubmedId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
47
|
+
}, z.core.$strip>>;
|
|
42
48
|
initialSampleSize: z.ZodOptional<z.ZodString>;
|
|
43
49
|
}, z.core.$strip>>;
|
|
44
50
|
pvalueMantissa: z.ZodOptional<z.ZodNumber>;
|
|
@@ -49,6 +55,63 @@ declare const RawGwasAssociationSchema: z.ZodObject<{
|
|
|
49
55
|
range: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
50
56
|
}, z.core.$strip>;
|
|
51
57
|
type RawGwasAssociation = z.infer<typeof RawGwasAssociationSchema>;
|
|
58
|
+
export declare const GwasEmbeddedSchema: z.ZodObject<{
|
|
59
|
+
_embedded: z.ZodOptional<z.ZodObject<{
|
|
60
|
+
associations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
61
|
+
_snpRsId: z.ZodOptional<z.ZodString>;
|
|
62
|
+
loci: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
63
|
+
strongestRiskAlleles: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
64
|
+
riskAlleleName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
65
|
+
}, z.core.$strip>>>;
|
|
66
|
+
authorReportedGenes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
67
|
+
geneName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
68
|
+
}, z.core.$strip>>>;
|
|
69
|
+
}, z.core.$strip>>>;
|
|
70
|
+
efoTraits: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
71
|
+
trait: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
72
|
+
}, z.core.$strip>>>;
|
|
73
|
+
study: z.ZodOptional<z.ZodObject<{
|
|
74
|
+
accessionId: z.ZodOptional<z.ZodString>;
|
|
75
|
+
publicationInfo: z.ZodOptional<z.ZodObject<{
|
|
76
|
+
pubmedId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
77
|
+
}, z.core.$strip>>;
|
|
78
|
+
initialSampleSize: z.ZodOptional<z.ZodString>;
|
|
79
|
+
}, z.core.$strip>>;
|
|
80
|
+
pvalueMantissa: z.ZodOptional<z.ZodNumber>;
|
|
81
|
+
pvalueExponent: z.ZodOptional<z.ZodNumber>;
|
|
82
|
+
riskFrequency: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
83
|
+
orPerCopyNum: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
84
|
+
betaNum: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
85
|
+
range: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
86
|
+
}, z.core.$strip>>>;
|
|
87
|
+
}, z.core.$strip>>;
|
|
88
|
+
page: z.ZodOptional<z.ZodObject<{
|
|
89
|
+
totalElements: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
}, z.core.$strip>>;
|
|
91
|
+
}, z.core.$strip>;
|
|
92
|
+
export declare const GwasTraitSearchResponseSchema: z.ZodObject<{
|
|
93
|
+
_embedded: z.ZodOptional<z.ZodObject<{
|
|
94
|
+
efoTraits: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
95
|
+
_links: z.ZodOptional<z.ZodObject<{
|
|
96
|
+
self: z.ZodOptional<z.ZodObject<{
|
|
97
|
+
href: z.ZodOptional<z.ZodString>;
|
|
98
|
+
}, z.core.$strip>>;
|
|
99
|
+
}, z.core.$strip>>;
|
|
100
|
+
}, z.core.$strip>>>;
|
|
101
|
+
}, z.core.$strip>>;
|
|
102
|
+
}, z.core.$strip>;
|
|
103
|
+
export declare const GwasSnpSearchResponseSchema: z.ZodObject<{
|
|
104
|
+
_embedded: z.ZodOptional<z.ZodObject<{
|
|
105
|
+
singleNucleotidePolymorphisms: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
106
|
+
rsId: z.ZodOptional<z.ZodString>;
|
|
107
|
+
_links: z.ZodOptional<z.ZodObject<{
|
|
108
|
+
associations: z.ZodOptional<z.ZodObject<{
|
|
109
|
+
href: z.ZodOptional<z.ZodString>;
|
|
110
|
+
}, z.core.$strip>>;
|
|
111
|
+
}, z.core.$strip>>;
|
|
112
|
+
}, z.core.$strip>>>;
|
|
113
|
+
}, z.core.$strip>>;
|
|
114
|
+
}, z.core.$strip>;
|
|
52
115
|
export declare function mapAssociation(a: RawGwasAssociation): GwasAssociation;
|
|
53
116
|
export interface GwasSearchOptions {
|
|
54
117
|
pValueThreshold?: number;
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
* per-SNP associations), by trait (EFO trait search then its associations), by
|
|
6
6
|
* variant (direct rsID associations), and by study (the associations of one
|
|
7
7
|
* GCST study accession).
|
|
8
|
+
*
|
|
9
|
+
* Absence policy: the sampled payloads show an explicit `null` for an absent
|
|
10
|
+
* leaf value, and the key set of one projection stays constant. A key is absent
|
|
11
|
+
* only when the projection that the request named excludes it.
|
|
8
12
|
*/
|
|
9
13
|
import { z } from "zod";
|
|
10
14
|
import { apiFetchValidated, describeApiError } from "./api-utils.js";
|
|
@@ -12,9 +16,16 @@ import { GWAS_BASE, GWAS_HEADERS } from "./gwas-catalog-config.js";
|
|
|
12
16
|
// GWAS Catalog raw wire shapes (HAL+JSON), validated at the fetch boundary.
|
|
13
17
|
// Every field is optional because the API omits absent values; leaf strings
|
|
14
18
|
// that the API can return as an explicit `null` are `.nullable()`.
|
|
19
|
+
//
|
|
20
|
+
// The `study` and `efoTraits` keys of an association exist only on some
|
|
21
|
+
// projections: `associationByStudy` nests the study, `associationByEfoTrait`
|
|
22
|
+
// nests the traits, and the gene path serves neither. Thus their absence is a
|
|
23
|
+
// property of the projection that the request named, and it is not drift.
|
|
15
24
|
const RawGwasStudySchema = z.object({
|
|
16
25
|
accessionId: z.string().optional(),
|
|
17
|
-
|
|
26
|
+
// The PubMed id is a field of the publication record, and never of the study
|
|
27
|
+
// record itself.
|
|
28
|
+
publicationInfo: z.object({ pubmedId: z.string().nullable().optional() }).optional(),
|
|
18
29
|
initialSampleSize: z.string().optional(),
|
|
19
30
|
});
|
|
20
31
|
// `_snpRsId` is not on the wire — the 'gene' search path assigns it after
|
|
@@ -36,18 +47,18 @@ const RawGwasAssociationSchema = z.object({
|
|
|
36
47
|
betaNum: z.number().nullable().optional(),
|
|
37
48
|
range: z.string().nullable().optional(),
|
|
38
49
|
});
|
|
39
|
-
const GwasEmbeddedSchema = z.object({
|
|
50
|
+
export const GwasEmbeddedSchema = z.object({
|
|
40
51
|
_embedded: z.object({ associations: z.array(RawGwasAssociationSchema).optional() }).optional(),
|
|
41
52
|
page: z.object({ totalElements: z.number().optional() }).optional(),
|
|
42
53
|
});
|
|
43
|
-
const GwasTraitSearchResponseSchema = z.object({
|
|
54
|
+
export const GwasTraitSearchResponseSchema = z.object({
|
|
44
55
|
_embedded: z
|
|
45
56
|
.object({
|
|
46
57
|
efoTraits: z.array(z.object({ _links: z.object({ self: z.object({ href: z.string().optional() }).optional() }).optional() })).optional(),
|
|
47
58
|
})
|
|
48
59
|
.optional(),
|
|
49
60
|
});
|
|
50
|
-
const GwasSnpSearchResponseSchema = z.object({
|
|
61
|
+
export const GwasSnpSearchResponseSchema = z.object({
|
|
51
62
|
_embedded: z
|
|
52
63
|
.object({
|
|
53
64
|
singleNucleotidePolymorphisms: z
|
|
@@ -79,7 +90,7 @@ export function mapAssociation(a) {
|
|
|
79
90
|
trait: traits.join("; "),
|
|
80
91
|
mappedGenes: [...new Set(genes)],
|
|
81
92
|
studyAccession: String(study.accessionId ?? ""),
|
|
82
|
-
pubmedId: String(study.pubmedId ?? ""),
|
|
93
|
+
pubmedId: String(study.publicationInfo?.pubmedId ?? ""),
|
|
83
94
|
sampleSize: String(study.initialSampleSize ?? ""),
|
|
84
95
|
};
|
|
85
96
|
}
|
|
@@ -123,7 +134,11 @@ export async function searchGwasCatalog(query, searchType, options = {}) {
|
|
|
123
134
|
associationsUrl = `${GWAS_BASE}/studies/${encodeURIComponent(query)}/associations?projection=associationByStudy&size=${limit}`;
|
|
124
135
|
}
|
|
125
136
|
else {
|
|
126
|
-
|
|
137
|
+
// `findByEfoTrait` matches the EXACT EFO trait label (case-insensitive),
|
|
138
|
+
// and it answers HTTP 200 with an empty `efoTraits` list when nothing
|
|
139
|
+
// matches. A paraphrase of a label thus reads as clean no-data, and the
|
|
140
|
+
// tool description warns the caller.
|
|
141
|
+
const traitRes = await apiFetchValidated(`${GWAS_BASE}/efoTraits/search/findByEfoTrait?trait=${encodeURIComponent(query)}`, GwasTraitSearchResponseSchema, {
|
|
127
142
|
headers: GWAS_HEADERS,
|
|
128
143
|
});
|
|
129
144
|
if (traitRes.isErr())
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* resolution failure aborts the assessment with `error.kind:
|
|
18
18
|
* "target-unresolved"` (per design §6).
|
|
19
19
|
*/
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
import type { Logger } from "../../lib/logger.js";
|
|
20
22
|
export interface ResolvedTarget {
|
|
21
23
|
/** Canonical id used as the entity-resolution anchor — preferred order: HGNC, then Ensembl. */
|
|
22
24
|
canonicalId: string;
|
|
@@ -48,12 +50,26 @@ export interface ResolvedTarget {
|
|
|
48
50
|
chembl: boolean;
|
|
49
51
|
};
|
|
50
52
|
}
|
|
53
|
+
export declare const HgncResponseSchema: z.ZodObject<{
|
|
54
|
+
response: z.ZodOptional<z.ZodObject<{
|
|
55
|
+
docs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
56
|
+
symbol: z.ZodOptional<z.ZodString>;
|
|
57
|
+
name: z.ZodOptional<z.ZodString>;
|
|
58
|
+
hgnc_id: z.ZodOptional<z.ZodString>;
|
|
59
|
+
ensembl_gene_id: z.ZodOptional<z.ZodString>;
|
|
60
|
+
uniprot_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
61
|
+
entrez_id: z.ZodOptional<z.ZodString>;
|
|
62
|
+
alias_symbol: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
63
|
+
prev_symbol: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
64
|
+
}, z.core.$strip>>>;
|
|
65
|
+
}, z.core.$strip>>;
|
|
66
|
+
}, z.core.$strip>;
|
|
51
67
|
/**
|
|
52
68
|
* Resolve a free-form target identifier to a canonical entity.
|
|
53
69
|
*
|
|
54
70
|
* @throws when the input cannot be mapped to any human gene/protein.
|
|
55
71
|
*/
|
|
56
|
-
export declare function resolveTarget(input: string): Promise<ResolvedTarget>;
|
|
72
|
+
export declare function resolveTarget(input: string, logger?: Logger): Promise<ResolvedTarget>;
|
|
57
73
|
export interface AutocompleteCandidate {
|
|
58
74
|
/** Approved HGNC symbol when known, otherwise the input symbol. */
|
|
59
75
|
symbol: string;
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* "target-unresolved"` (per design §6).
|
|
19
19
|
*/
|
|
20
20
|
import { z } from "zod";
|
|
21
|
+
import { createNoopLogger } from "../../lib/console-logger.js";
|
|
21
22
|
import { apiFetchValidated } from "./api-utils.js";
|
|
22
23
|
import { resolveSymbolToEnsemblId } from "./ensembl-client.js";
|
|
23
24
|
import { searchTargets as searchChemblTargets } from "./chembl-client.js";
|
|
@@ -33,7 +34,9 @@ const HGNC_RE = /^HGNC:\d+$/;
|
|
|
33
34
|
// HGNC search payload, validated at the fetch boundary. Every field is optional
|
|
34
35
|
// because the API omits absent values; each read below is optional-chained /
|
|
35
36
|
// defaulted, so a missing field degrades gracefully rather than throwing.
|
|
36
|
-
|
|
37
|
+
// The schema is exported for the golden-fixture table, which is the only place
|
|
38
|
+
// that asserts the contract itself instead of the resolved entity.
|
|
39
|
+
export const HgncResponseSchema = z.object({
|
|
37
40
|
response: z
|
|
38
41
|
.object({
|
|
39
42
|
docs: z
|
|
@@ -69,7 +72,6 @@ const UniprotResponseSchema = z.object({
|
|
|
69
72
|
synonyms: z.array(z.object({ value: z.string().optional() })).optional(),
|
|
70
73
|
}))
|
|
71
74
|
.optional(),
|
|
72
|
-
proteinFamily: z.string().optional(),
|
|
73
75
|
extraAttributes: z.object({ uniParcId: z.string().optional() }).optional(),
|
|
74
76
|
keywords: z.array(z.object({ name: z.string().optional() })).optional(),
|
|
75
77
|
}))
|
|
@@ -124,7 +126,8 @@ function extractProteinFamily(uniprotKeywords) {
|
|
|
124
126
|
*
|
|
125
127
|
* @throws when the input cannot be mapped to any human gene/protein.
|
|
126
128
|
*/
|
|
127
|
-
export async function resolveTarget(input) {
|
|
129
|
+
export async function resolveTarget(input, logger) {
|
|
130
|
+
const log = (logger ?? createNoopLogger()).named("identifier-resolver").with({ target: input });
|
|
128
131
|
const trimmed = input.trim();
|
|
129
132
|
if (!trimmed)
|
|
130
133
|
throw new Error("Target identifier is required");
|
|
@@ -199,7 +202,13 @@ export async function resolveTarget(input) {
|
|
|
199
202
|
// Step 4: ChEMBL
|
|
200
203
|
let chemblId = seedChembl;
|
|
201
204
|
if (!chemblId && symbolForEnsembl) {
|
|
202
|
-
|
|
205
|
+
// `searchTargets` answers an unknown symbol with an empty list, thus a throw
|
|
206
|
+
// here is always an unexpected cause. Without this record the ChEMBL id stays
|
|
207
|
+
// null and every downstream collector reports a false "no ChEMBL entry".
|
|
208
|
+
const targets = await searchChemblTargets(symbolForEnsembl, 5).catch((error) => {
|
|
209
|
+
log.error("ChEMBL target search failed", { symbol: symbolForEnsembl, ...log.errorFields(error) });
|
|
210
|
+
return [];
|
|
211
|
+
});
|
|
203
212
|
const human = targets.find((t) => t.organism === "Homo sapiens");
|
|
204
213
|
chemblId = (human ?? targets[0])?.targetChemblId ?? null;
|
|
205
214
|
}
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* Consortium) Solr API.
|
|
4
4
|
*
|
|
5
5
|
* Used by §3.10.1 (Knockout phenotype card).
|
|
6
|
+
*
|
|
7
|
+
* Absence policy: the Solr API omits the key of an absent value, and it never
|
|
8
|
+
* sends an explicit `null`. Thus a maybe-absent field carries `.optional()`,
|
|
9
|
+
* not `.nullable()`.
|
|
6
10
|
*/
|
|
7
11
|
export interface MpTerm {
|
|
8
12
|
id: string;
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* Consortium) Solr API.
|
|
4
4
|
*
|
|
5
5
|
* Used by §3.10.1 (Knockout phenotype card).
|
|
6
|
+
*
|
|
7
|
+
* Absence policy: the Solr API omits the key of an absent value, and it never
|
|
8
|
+
* sends an explicit `null`. Thus a maybe-absent field carries `.optional()`,
|
|
9
|
+
* not `.nullable()`.
|
|
6
10
|
*/
|
|
7
11
|
import { z } from "zod";
|
|
8
12
|
import { apiFetchValidated, describeApiError, isUnexpectedApiError } from "./api-utils.js";
|
|
@@ -10,13 +10,14 @@
|
|
|
10
10
|
* panels never list a sibling receptor-complex as a developable hit.
|
|
11
11
|
*/
|
|
12
12
|
import { z } from "zod";
|
|
13
|
-
|
|
13
|
+
import type { Logger } from "../../lib/logger.js";
|
|
14
|
+
export declare const IupharTargetSchema: z.ZodObject<{
|
|
14
15
|
targetId: z.ZodNumber;
|
|
15
16
|
name: z.ZodString;
|
|
16
17
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
17
18
|
familyIds: z.ZodArray<z.ZodNumber>;
|
|
18
19
|
subunitIds: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
19
|
-
complexIds: z.ZodArray<z.ZodNumber
|
|
20
|
+
complexIds: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
20
21
|
subunitType: z.ZodOptional<z.ZodString>;
|
|
21
22
|
}, z.core.$strip>;
|
|
22
23
|
export type IupharTarget = z.infer<typeof IupharTargetSchema>;
|
|
@@ -53,7 +54,7 @@ export declare function getFamilyHeterodimers(uniprotOrGeneSymbol: string): Prom
|
|
|
53
54
|
* Example: getAccessoryProteinNames("CALCR") → ["RAMP1", "RAMP2", "RAMP3"].
|
|
54
55
|
*/
|
|
55
56
|
export declare function getAccessoryProteinNames(uniprotOrGeneSymbol: string): Promise<string[]>;
|
|
56
|
-
declare const IupharFamilySchema: z.ZodObject<{
|
|
57
|
+
export declare const IupharFamilySchema: z.ZodObject<{
|
|
57
58
|
familyId: z.ZodOptional<z.ZodNumber>;
|
|
58
59
|
name: z.ZodOptional<z.ZodString>;
|
|
59
60
|
targetIds: z.ZodArray<z.ZodNumber>;
|
|
@@ -62,6 +63,11 @@ declare const IupharFamilySchema: z.ZodObject<{
|
|
|
62
63
|
}, z.core.$strip>;
|
|
63
64
|
export type IupharFamily = z.infer<typeof IupharFamilySchema>;
|
|
64
65
|
export declare function getFamily(familyId: number): Promise<IupharFamily | null>;
|
|
66
|
+
export declare const IupharDatabaseLinkSchema: z.ZodObject<{
|
|
67
|
+
accession: z.ZodOptional<z.ZodString>;
|
|
68
|
+
database: z.ZodOptional<z.ZodString>;
|
|
69
|
+
species: z.ZodOptional<z.ZodString>;
|
|
70
|
+
}, z.core.$strip>;
|
|
65
71
|
/** Fetch the UniProtKB cross-references (human only) for an IUPHAR target. */
|
|
66
72
|
export declare function getTargetHumanUniprots(targetId: number): Promise<string[]>;
|
|
67
73
|
/**
|
|
@@ -71,5 +77,4 @@ export declare function getTargetHumanUniprots(targetId: number): Promise<string
|
|
|
71
77
|
* CALCRL accession; the AMY1/2/3 complexes are excluded because they are
|
|
72
78
|
* heterodimers, not separate primary proteins.
|
|
73
79
|
*/
|
|
74
|
-
export declare function getFamilySiblingUniprots(uniprotOrGeneSymbol: string): Promise<string[]>;
|
|
75
|
-
export {};
|
|
80
|
+
export declare function getFamilySiblingUniprots(uniprotOrGeneSymbol: string, logger?: Logger): Promise<string[]>;
|