Skip to content

Commit d505bd6

Browse files
committed
Format the code
1 parent 9f86a90 commit d505bd6

File tree

5 files changed

+94
-124
lines changed

5 files changed

+94
-124
lines changed

src/tools/findRecordsByCitationKey.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ import {
66
generateFinderPathVariants,
77
lookupZoteroMetadataByCitationKey,
88
} from "../utils/zoteroMetadata.js";
9-
import {
10-
convertDevonthinkRecordHelper,
11-
} from "../utils/jxaHelpers.js";
9+
import { convertDevonthinkRecordHelper } from "../utils/jxaHelpers.js";
1210
import type {
1311
ZoteroMatchType,
1412
ZoteroMetadataDescriptor,
@@ -20,22 +18,21 @@ type ToolInput = z.infer<typeof ToolInputSchema>;
2018

2119
const FinderPathLookupSchema = z
2220
.object({
23-
citationKey: z.string().min(1, "citationKey must not be empty").describe("Zotero citation key"),
24-
zoteroJsonPath: z
25-
.string()
26-
.optional()
27-
.describe("Override path to Zotero JSON export"),
28-
zoteroBibPath: z
21+
citationKey: z
2922
.string()
30-
.optional()
31-
.describe("Override path to Zotero BibTeX export"),
23+
.min(1, "citationKey must not be empty")
24+
.describe("Zotero citation key"),
25+
zoteroJsonPath: z.string().optional().describe("Override path to Zotero JSON export"),
26+
zoteroBibPath: z.string().optional().describe("Override path to Zotero BibTeX export"),
3227
maxRecordsPerPath: z
3328
.number()
3429
.int()
3530
.min(1)
3631
.max(50)
3732
.optional()
38-
.describe("Maximum number of DEVONthink records to return for each attachment path (default 5)"),
33+
.describe(
34+
"Maximum number of DEVONthink records to return for each attachment path (default 5)",
35+
),
3936
})
4037
.strict();
4138

@@ -284,4 +281,3 @@ export const findRecordsByCitationKeyTool: Tool = {
284281
inputSchema: zodToJsonSchema(FinderPathLookupSchema) as ToolInput,
285282
run: findRecordsByCitationKey,
286283
};
287-

src/tools/getZoteroMetadata.ts

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,15 @@ import { executeJxa } from "../applescript/execute.js";
55
import { escapeStringForJXA, isJXASafeString } from "../utils/escapeString.js";
66
import { getRecordLookupHelpers, getDatabaseHelper } from "../utils/jxaHelpers.js";
77
import { lookupZoteroMetadataByPath } from "../utils/zoteroMetadata.js";
8-
import type {
9-
ZoteroMatchType,
10-
ZoteroMetadataDescriptor,
11-
} from "../utils/zoteroMetadata.js";
8+
import type { ZoteroMatchType, ZoteroMetadataDescriptor } from "../utils/zoteroMetadata.js";
129

1310
const ToolInputSchema = ToolSchema.shape.inputSchema;
1411
type ToolInput = z.infer<typeof ToolInputSchema>;
1512

1613
const GetZoteroMetadataSchema = z
1714
.object({
1815
uuid: z.string().optional().describe("UUID of the DEVONthink record"),
19-
id: z
20-
.number()
21-
.optional()
22-
.describe("DEVONthink record ID (requires databaseName)"),
16+
id: z.number().optional().describe("DEVONthink record ID (requires databaseName)"),
2317
databaseName: z
2418
.string()
2519
.optional()
@@ -141,19 +135,15 @@ const buildRecordLookupScript = (input: {
141135
parts.push(` let resolvedDatabase = null;`);
142136

143137
if (input.uuid) {
144-
parts.push(
145-
` lookupOptions["uuid"] = "${escapeStringForJXA(input.uuid)}";`,
146-
);
138+
parts.push(` lookupOptions["uuid"] = "${escapeStringForJXA(input.uuid)}";`);
147139
}
148140

149141
if (input.id !== undefined) {
150142
parts.push(` lookupOptions["id"] = ${input.id};`);
151143
}
152144

153145
if (input.recordPath) {
154-
parts.push(
155-
` lookupOptions["path"] = "${escapeStringForJXA(input.recordPath)}";`,
156-
);
146+
parts.push(` lookupOptions["path"] = "${escapeStringForJXA(input.recordPath)}";`);
157147
}
158148

159149
if (input.databaseName) {
@@ -175,8 +165,8 @@ const buildRecordLookupScript = (input: {
175165
parts.push(` const response = {};`);
176166
parts.push(` response["success"] = false;`);
177167
parts.push(
178-
` const lookupError = lookupResult && lookupResult.error ? lookupResult.error : "Record not found";`,
179-
);
168+
` const lookupError = lookupResult && lookupResult.error ? lookupResult.error : "Record not found";`,
169+
);
180170
parts.push(` response["error"] = lookupError;`);
181171
parts.push(` return JSON.stringify(response);`);
182172
parts.push(` }`);
@@ -192,17 +182,21 @@ const buildRecordLookupScript = (input: {
192182
parts.push(` const response = {};`);
193183
parts.push(` response["success"] = true;`);
194184
parts.push(` response["finderPath"] = finderPath;`);
195-
parts.push(
196-
` response["lookupMethod"] = lookupResult.method ? lookupResult.method : null;`,
197-
);
185+
parts.push(` response["lookupMethod"] = lookupResult.method ? lookupResult.method : null;`);
198186

199187
parts.push(` const recordInfo = {};`);
200-
parts.push(` try { recordInfo["uuid"] = record.uuid(); } catch (e) { recordInfo["uuid"] = null; }`);
201-
parts.push(` try { recordInfo["id"] = record.id(); } catch (e) { recordInfo["id"] = null; }`);
202-
parts.push(` try { recordInfo["name"] = record.name(); } catch (e) { recordInfo["name"] = null; }`);
203188
parts.push(
204-
` try { recordInfo["location"] = record.location(); } catch (e) { recordInfo["location"] = null; }`,
205-
);
189+
` try { recordInfo["uuid"] = record.uuid(); } catch (e) { recordInfo["uuid"] = null; }`,
190+
);
191+
parts.push(
192+
` try { recordInfo["id"] = record.id(); } catch (e) { recordInfo["id"] = null; }`,
193+
);
194+
parts.push(
195+
` try { recordInfo["name"] = record.name(); } catch (e) { recordInfo["name"] = null; }`,
196+
);
197+
parts.push(
198+
` try { recordInfo["location"] = record.location(); } catch (e) { recordInfo["location"] = null; }`,
199+
);
206200
parts.push(` recordInfo["path"] = finderPath;`);
207201
parts.push(` try {`);
208202
parts.push(` const db = record.database();`);
@@ -234,9 +228,7 @@ const buildRecordLookupScript = (input: {
234228
return parts.join("\n");
235229
};
236230

237-
const getRecordFinderPath = async (
238-
input: GetZoteroMetadataInput,
239-
): Promise<RecordLookupResult> => {
231+
const getRecordFinderPath = async (input: GetZoteroMetadataInput): Promise<RecordLookupResult> => {
240232
try {
241233
const script = buildRecordLookupScript(input);
242234
return await executeJxa<RecordLookupResult>(script);
@@ -251,15 +243,7 @@ const getRecordFinderPath = async (
251243
const getZoteroMetadata = async (
252244
input: GetZoteroMetadataInput,
253245
): Promise<ZoteroMetadataToolSuccess | ZoteroMetadataToolFailure> => {
254-
const {
255-
uuid,
256-
id,
257-
databaseName,
258-
recordPath,
259-
finderPath,
260-
zoteroJsonPath,
261-
zoteroBibPath,
262-
} = input;
246+
const { uuid, id, databaseName, recordPath, finderPath, zoteroJsonPath, zoteroBibPath } = input;
263247

264248
const metadataJsonPath = zoteroJsonPath ?? process.env.ZOTERO_BIBLIOGRAPHY_JSON ?? null;
265249
const metadataBibPath = zoteroBibPath ?? process.env.ZOTERO_BIBLIOGRAPHY_BIB ?? null;

src/utils/zoteroMetadata.ts

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,7 @@ const collectJsonAttachmentPaths = (item: Record<string, unknown>): string[] =>
242242
return Array.from(paths);
243243
};
244244

245-
const getFirstStringFromKeys = (
246-
source: Record<string, unknown>,
247-
keys: string[],
248-
): string | null => {
245+
const getFirstStringFromKeys = (source: Record<string, unknown>, keys: string[]): string | null => {
249246
for (const key of keys) {
250247
const candidate = source[key];
251248
if (typeof candidate === "string" && candidate.trim()) {
@@ -277,12 +274,9 @@ const findMatchingTopLevelField = (
277274
};
278275

279276
const buildJsonDescriptor = (item: Record<string, unknown>): ZoteroMetadataDescriptor => {
280-
const citationKey =
281-
getFirstStringFromKeys(item, ["citationKey", "citationkey", "id"]) ?? null;
282-
const zoteroId =
283-
getFirstStringFromKeys(item, ["zoteroId", "zotero_id", "key", "id"]) ?? null;
284-
const title =
285-
getFirstStringFromKeys(item, ["title"]) ?? null;
277+
const citationKey = getFirstStringFromKeys(item, ["citationKey", "citationkey", "id"]) ?? null;
278+
const zoteroId = getFirstStringFromKeys(item, ["zoteroId", "zotero_id", "key", "id"]) ?? null;
279+
const title = getFirstStringFromKeys(item, ["title"]) ?? null;
286280

287281
return {
288282
source: "json",
@@ -294,7 +288,10 @@ const buildJsonDescriptor = (item: Record<string, unknown>): ZoteroMetadataDescr
294288
};
295289

296290
const parseBibFileField = (value: string): string[] => {
297-
const segments = value.split(";").map((segment) => segment.trim()).filter(Boolean);
291+
const segments = value
292+
.split(";")
293+
.map((segment) => segment.trim())
294+
.filter(Boolean);
298295
const paths: string[] = [];
299296

300297
for (const segment of segments) {
@@ -339,11 +336,7 @@ const collectBibAttachmentPaths = (entry: BibEntry): string[] => {
339336

340337
const buildBibDescriptor = (entry: BibEntry): ZoteroMetadataDescriptor => {
341338
const citationKey = entry.key ?? null;
342-
const zoteroId =
343-
entry.fields.zotero_id ??
344-
entry.fields.id ??
345-
entry.fields.citationkey ??
346-
null;
339+
const zoteroId = entry.fields.zotero_id ?? entry.fields.id ?? entry.fields.citationkey ?? null;
347340
const title = entry.fields.title ?? entry.fields["title"] ?? null;
348341

349342
return {
@@ -402,11 +395,7 @@ const findPathInJsonValue = (
402395
if (value && typeof value === "object") {
403396
const obj = value as Record<string, unknown>;
404397
for (const key of Object.keys(obj)) {
405-
const childResult = findPathInJsonValue(
406-
obj[key],
407-
variants,
408-
propertyPath.concat(key),
409-
);
398+
const childResult = findPathInJsonValue(obj[key], variants, propertyPath.concat(key));
410399
if (childResult) {
411400
return childResult;
412401
}
@@ -671,7 +660,11 @@ const lookupCitationInJson = async (
671660
if (!entry || typeof entry !== "object") continue;
672661
const item = entry as Record<string, unknown>;
673662
const descriptor = buildJsonDescriptor(item);
674-
const matchInfo = findMatchingTopLevelField(item, ["citationKey", "citationkey", "id"], citationKey);
663+
const matchInfo = findMatchingTopLevelField(
664+
item,
665+
["citationKey", "citationkey", "id"],
666+
citationKey,
667+
);
675668
if (matchInfo) {
676669
return {
677670
success: true,
@@ -807,7 +800,9 @@ export const lookupZoteroMetadataByCitationKey = async (
807800
if (jsonMatch) {
808801
return jsonMatch;
809802
}
810-
errors.push(`No entry with citation key '${trimmedKey}' in JSON metadata at ${jsonPath}`);
803+
errors.push(
804+
`No entry with citation key '${trimmedKey}' in JSON metadata at ${jsonPath}`,
805+
);
811806
} else {
812807
errors.push(`JSON metadata file not found at ${jsonPath}`);
813808
}
@@ -820,7 +815,9 @@ export const lookupZoteroMetadataByCitationKey = async (
820815
if (bibMatch) {
821816
return bibMatch;
822817
}
823-
errors.push(`No entry with citation key '${trimmedKey}' in BibTeX metadata at ${bibPath}`);
818+
errors.push(
819+
`No entry with citation key '${trimmedKey}' in BibTeX metadata at ${bibPath}`,
820+
);
824821
} else {
825822
errors.push(`BibTeX metadata file not found at ${bibPath}`);
826823
}
Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,43 @@
11
[
2-
{
3-
"id": "smith2024deep",
4-
"type": "article-journal",
5-
"title": "Deep Learning for Citation Matching",
6-
"author": [
7-
{
8-
"family": "Smith",
9-
"given": "Alex"
10-
}
11-
],
12-
"issued": {
13-
"date-parts": [
14-
[
15-
2024
16-
]
17-
]
18-
},
19-
"attachments": [
20-
{
21-
"title": "Full Text PDF",
22-
"localPath": "/Users/alex/Documents/Zotero/storage/ABC12345/Smith2024.pdf"
23-
},
24-
{
25-
"title": "Supplement",
26-
"localPath": "file:///Users/alex/Documents/Zotero/storage/ABC12345/Smith2024-supplement.pdf"
27-
}
28-
]
29-
},
30-
{
31-
"id": "miller2023notes",
32-
"type": "paper-conference",
33-
"title": "Notes on Knowledge Graphs",
34-
"author": [
35-
{
36-
"family": "Miller",
37-
"given": "Jordan"
38-
}
39-
],
40-
"attachments": [
41-
{
42-
"title": "Conference Paper",
43-
"path": "/Users/alex/Documents/Zotero/storage/XYZ9876/Miller2023.pdf"
44-
}
45-
]
46-
}
2+
{
3+
"id": "smith2024deep",
4+
"type": "article-journal",
5+
"title": "Deep Learning for Citation Matching",
6+
"author": [
7+
{
8+
"family": "Smith",
9+
"given": "Alex"
10+
}
11+
],
12+
"issued": {
13+
"date-parts": [[2024]]
14+
},
15+
"attachments": [
16+
{
17+
"title": "Full Text PDF",
18+
"localPath": "/Users/alex/Documents/Zotero/storage/ABC12345/Smith2024.pdf"
19+
},
20+
{
21+
"title": "Supplement",
22+
"localPath": "file:///Users/alex/Documents/Zotero/storage/ABC12345/Smith2024-supplement.pdf"
23+
}
24+
]
25+
},
26+
{
27+
"id": "miller2023notes",
28+
"type": "paper-conference",
29+
"title": "Notes on Knowledge Graphs",
30+
"author": [
31+
{
32+
"family": "Miller",
33+
"given": "Jordan"
34+
}
35+
],
36+
"attachments": [
37+
{
38+
"title": "Conference Paper",
39+
"path": "/Users/alex/Documents/Zotero/storage/XYZ9876/Miller2023.pdf"
40+
}
41+
]
42+
}
4743
]

tests/utils/zoteroMetadata.test.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ describe("lookupZoteroMetadataByPath", () => {
1919
});
2020

2121
it("finds metadata from the JSON export when the attachment path matches directly", async () => {
22-
const finderPath =
23-
"/Users/alex/Documents/Zotero/storage/ABC12345/Smith2024.pdf";
22+
const finderPath = "/Users/alex/Documents/Zotero/storage/ABC12345/Smith2024.pdf";
2423

2524
const result = await lookupZoteroMetadataByPath(finderPath, {
2625
jsonPath: jsonFixturePath,
@@ -43,8 +42,7 @@ describe("lookupZoteroMetadataByPath", () => {
4342
});
4443

4544
it("finds metadata from the JSON export when the attachment stores a file URL", async () => {
46-
const finderPath =
47-
"/Users/alex/Documents/Zotero/storage/ABC12345/Smith2024-supplement.pdf";
45+
const finderPath = "/Users/alex/Documents/Zotero/storage/ABC12345/Smith2024-supplement.pdf";
4846

4947
const result = await lookupZoteroMetadataByPath(finderPath, {
5048
jsonPath: jsonFixturePath,
@@ -64,8 +62,7 @@ describe("lookupZoteroMetadataByPath", () => {
6462
});
6563

6664
it("falls back to the BibTeX export when JSON is missing the attachment", async () => {
67-
const finderPath =
68-
"/Users/alex/Documents/Zotero/storage/GAR5566/Garcia2021.pdf";
65+
const finderPath = "/Users/alex/Documents/Zotero/storage/GAR5566/Garcia2021.pdf";
6966

7067
const result = await lookupZoteroMetadataByPath(finderPath, {
7168
jsonPath: jsonFixturePath,

0 commit comments

Comments
 (0)