@ncukondo/reference-manager 0.3.0 → 0.4.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.
Files changed (113) hide show
  1. package/README.md +267 -109
  2. package/dist/chunks/file-watcher-B-SiUw5f.js +1557 -0
  3. package/dist/chunks/file-watcher-B-SiUw5f.js.map +1 -0
  4. package/dist/chunks/{search-Be9vzUIH.js → index-DLIGxQaB.js} +399 -89
  5. package/dist/chunks/index-DLIGxQaB.js.map +1 -0
  6. package/dist/chunks/loader-DuzyKV70.js +394 -0
  7. package/dist/chunks/loader-DuzyKV70.js.map +1 -0
  8. package/dist/cli/commands/add.d.ts +3 -3
  9. package/dist/cli/commands/add.d.ts.map +1 -1
  10. package/dist/cli/commands/cite.d.ts +3 -3
  11. package/dist/cli/commands/cite.d.ts.map +1 -1
  12. package/dist/cli/commands/fulltext.d.ts +5 -34
  13. package/dist/cli/commands/fulltext.d.ts.map +1 -1
  14. package/dist/cli/commands/list.d.ts +3 -3
  15. package/dist/cli/commands/list.d.ts.map +1 -1
  16. package/dist/cli/commands/mcp.d.ts +16 -0
  17. package/dist/cli/commands/mcp.d.ts.map +1 -0
  18. package/dist/cli/commands/remove.d.ts +3 -3
  19. package/dist/cli/commands/remove.d.ts.map +1 -1
  20. package/dist/cli/commands/search.d.ts +3 -3
  21. package/dist/cli/commands/search.d.ts.map +1 -1
  22. package/dist/cli/commands/server.d.ts +2 -0
  23. package/dist/cli/commands/server.d.ts.map +1 -1
  24. package/dist/cli/commands/update.d.ts +3 -3
  25. package/dist/cli/commands/update.d.ts.map +1 -1
  26. package/dist/cli/execution-context.d.ts +23 -36
  27. package/dist/cli/execution-context.d.ts.map +1 -1
  28. package/dist/cli/index.d.ts.map +1 -1
  29. package/dist/cli/server-client.d.ts +24 -40
  30. package/dist/cli/server-client.d.ts.map +1 -1
  31. package/dist/cli/server-detection.d.ts +1 -0
  32. package/dist/cli/server-detection.d.ts.map +1 -1
  33. package/dist/cli.js +21060 -317
  34. package/dist/cli.js.map +1 -1
  35. package/dist/config/defaults.d.ts.map +1 -1
  36. package/dist/config/loader.d.ts.map +1 -1
  37. package/dist/config/schema.d.ts +2 -3
  38. package/dist/config/schema.d.ts.map +1 -1
  39. package/dist/core/csl-json/types.d.ts +3 -0
  40. package/dist/core/csl-json/types.d.ts.map +1 -1
  41. package/dist/core/library-interface.d.ts +100 -0
  42. package/dist/core/library-interface.d.ts.map +1 -0
  43. package/dist/core/library.d.ts +29 -46
  44. package/dist/core/library.d.ts.map +1 -1
  45. package/dist/features/operations/add.d.ts +2 -2
  46. package/dist/features/operations/add.d.ts.map +1 -1
  47. package/dist/features/operations/cite.d.ts +2 -2
  48. package/dist/features/operations/cite.d.ts.map +1 -1
  49. package/dist/features/operations/fulltext/attach.d.ts +47 -0
  50. package/dist/features/operations/fulltext/attach.d.ts.map +1 -0
  51. package/dist/features/operations/fulltext/detach.d.ts +38 -0
  52. package/dist/features/operations/fulltext/detach.d.ts.map +1 -0
  53. package/dist/features/operations/fulltext/get.d.ts +41 -0
  54. package/dist/features/operations/fulltext/get.d.ts.map +1 -0
  55. package/dist/features/operations/fulltext/index.d.ts +9 -0
  56. package/dist/features/operations/fulltext/index.d.ts.map +1 -0
  57. package/dist/features/operations/index.d.ts +15 -0
  58. package/dist/features/operations/index.d.ts.map +1 -0
  59. package/dist/features/operations/library-operations.d.ts +64 -0
  60. package/dist/features/operations/library-operations.d.ts.map +1 -0
  61. package/dist/features/operations/list.d.ts +2 -2
  62. package/dist/features/operations/list.d.ts.map +1 -1
  63. package/dist/features/operations/operations-library.d.ts +36 -0
  64. package/dist/features/operations/operations-library.d.ts.map +1 -0
  65. package/dist/features/operations/remove.d.ts +4 -4
  66. package/dist/features/operations/remove.d.ts.map +1 -1
  67. package/dist/features/operations/search.d.ts +2 -2
  68. package/dist/features/operations/search.d.ts.map +1 -1
  69. package/dist/features/operations/update.d.ts +2 -2
  70. package/dist/features/operations/update.d.ts.map +1 -1
  71. package/dist/features/search/matcher.d.ts.map +1 -1
  72. package/dist/features/search/normalizer.d.ts +12 -0
  73. package/dist/features/search/normalizer.d.ts.map +1 -1
  74. package/dist/features/search/tokenizer.d.ts.map +1 -1
  75. package/dist/features/search/types.d.ts +1 -1
  76. package/dist/features/search/types.d.ts.map +1 -1
  77. package/dist/features/search/uppercase.d.ts +41 -0
  78. package/dist/features/search/uppercase.d.ts.map +1 -0
  79. package/dist/index.js +24 -192
  80. package/dist/index.js.map +1 -1
  81. package/dist/mcp/context.d.ts +19 -0
  82. package/dist/mcp/context.d.ts.map +1 -0
  83. package/dist/mcp/index.d.ts +20 -0
  84. package/dist/mcp/index.d.ts.map +1 -0
  85. package/dist/mcp/resources/index.d.ts +10 -0
  86. package/dist/mcp/resources/index.d.ts.map +1 -0
  87. package/dist/mcp/resources/library.d.ts +26 -0
  88. package/dist/mcp/resources/library.d.ts.map +1 -0
  89. package/dist/mcp/tools/add.d.ts +17 -0
  90. package/dist/mcp/tools/add.d.ts.map +1 -0
  91. package/dist/mcp/tools/cite.d.ts +15 -0
  92. package/dist/mcp/tools/cite.d.ts.map +1 -0
  93. package/dist/mcp/tools/fulltext.d.ts +51 -0
  94. package/dist/mcp/tools/fulltext.d.ts.map +1 -0
  95. package/dist/mcp/tools/index.d.ts +12 -0
  96. package/dist/mcp/tools/index.d.ts.map +1 -0
  97. package/dist/mcp/tools/list.d.ts +13 -0
  98. package/dist/mcp/tools/list.d.ts.map +1 -0
  99. package/dist/mcp/tools/remove.d.ts +19 -0
  100. package/dist/mcp/tools/remove.d.ts.map +1 -0
  101. package/dist/mcp/tools/search.d.ts +13 -0
  102. package/dist/mcp/tools/search.d.ts.map +1 -0
  103. package/dist/server/index.d.ts +23 -1
  104. package/dist/server/index.d.ts.map +1 -1
  105. package/dist/server/routes/references.d.ts.map +1 -1
  106. package/dist/server.js +5 -271
  107. package/dist/server.js.map +1 -1
  108. package/package.json +2 -1
  109. package/dist/chunks/detector-DHztTaFY.js +0 -619
  110. package/dist/chunks/detector-DHztTaFY.js.map +0 -1
  111. package/dist/chunks/loader-mQ25o6cV.js +0 -1054
  112. package/dist/chunks/loader-mQ25o6cV.js.map +0 -1
  113. package/dist/chunks/search-Be9vzUIH.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"loader-mQ25o6cV.js","sources":["../../src/core/identifier/normalize.ts","../../src/core/identifier/generator.ts","../../src/core/identifier/uuid.ts","../../src/core/reference.ts","../../src/utils/hash.ts","../../src/core/csl-json/parser.ts","../../src/core/csl-json/serializer.ts","../../src/core/library.ts","../../src/config/schema.ts","../../src/config/defaults.ts","../../src/config/loader.ts"],"sourcesContent":["/**\n * Normalize text for identifier generation\n * Converts to lowercase, converts spaces to underscores, keeps only alphanumeric and underscores\n * @param text - Text to normalize\n * @returns Normalized text (ASCII alphanumeric and underscores only)\n */\nexport function normalizeText(text: string): string {\n return text\n .toLowerCase()\n .replace(/\\s+/g, \"_\") // Convert spaces to underscores\n .replace(/[^a-z0-9_]/g, \"\") // Keep only alphanumeric and underscores\n .replace(/_+/g, \"_\") // Collapse multiple underscores\n .replace(/^_|_$/g, \"\"); // Remove leading/trailing underscores\n}\n\n/**\n * Normalize author name for identifier\n * @param name - Author name to normalize\n * @returns Normalized name (max 32 chars)\n */\nexport function normalizeAuthorName(name: string): string {\n const normalized = normalizeText(name);\n return normalized.slice(0, 32);\n}\n\n/**\n * Create a title slug for identifier\n * @param title - Title to create slug from\n * @returns Title slug (max 32 chars)\n */\nexport function normalizeTitleSlug(title: string): string {\n const normalized = normalizeText(title);\n return normalized.slice(0, 32);\n}\n","import type { CslItem } from \"../csl-json/types\";\nimport { normalizeAuthorName, normalizeTitleSlug } from \"./normalize\";\n\n/**\n * Extract author name from CSL-JSON item\n * Returns family name, literal name, or empty string\n */\nfunction extractAuthorName(item: CslItem): string {\n if (!item.author || item.author.length === 0) {\n return \"\";\n }\n\n const firstAuthor = item.author[0];\n if (!firstAuthor) {\n return \"\";\n }\n\n // Try family name first\n if (firstAuthor.family) {\n return normalizeAuthorName(firstAuthor.family);\n }\n\n // Try literal name (e.g., institutional authors)\n if (firstAuthor.literal) {\n return normalizeAuthorName(firstAuthor.literal);\n }\n\n return \"\";\n}\n\n/**\n * Extract year from CSL-JSON item\n * Returns year string or empty string\n */\nfunction extractYear(item: CslItem): string {\n if (!item.issued || !item.issued[\"date-parts\"] || item.issued[\"date-parts\"].length === 0) {\n return \"\";\n }\n\n const dateParts = item.issued[\"date-parts\"][0];\n if (!dateParts || dateParts.length === 0) {\n return \"\";\n }\n\n const year = dateParts[0];\n return year ? year.toString() : \"\";\n}\n\n/**\n * Determine the title part of the ID based on author, year, and title availability\n * @param hasAuthor - Whether author is available\n * @param hasYear - Whether year is available\n * @param title - Title slug\n * @returns Title part of the ID\n */\nfunction determineTitlePart(hasAuthor: boolean, hasYear: boolean, title: string): string {\n // No title part needed if both author and year are present\n if (hasAuthor && hasYear) {\n return \"\";\n }\n\n // Add title if available\n if (title) {\n return `-${title}`;\n }\n\n // Add \"untitled\" only if both author and year are missing\n if (!hasAuthor && !hasYear) {\n return \"-untitled\";\n }\n\n return \"\";\n}\n\n/**\n * Generate a BibTeX-style ID for a CSL-JSON item\n * Format: <FirstAuthorFamily>-<Year>[<TitleSlug>][a-z suffix]\n * @param item - CSL-JSON item\n * @returns Generated ID\n */\nexport function generateId(item: CslItem): string {\n const author = extractAuthorName(item);\n const year = extractYear(item);\n const title = item.title ? normalizeTitleSlug(item.title) : \"\";\n\n // Build base ID with fallbacks\n const authorPart = author || \"anon\";\n const yearPart = year || \"nd\"; // no date\n const titlePart = determineTitlePart(Boolean(author), Boolean(year), title);\n\n return `${authorPart}-${yearPart}${titlePart}`;\n}\n\n/**\n * Generate suffix for collision handling\n * a, b, c, ..., z, aa, ab, ...\n * @param index - Collision index (0 = no suffix, 1 = 'a', 2 = 'b', ...)\n * @returns Suffix string\n */\nfunction generateSuffix(index: number): string {\n if (index === 0) {\n return \"\";\n }\n\n let suffix = \"\";\n let num = index;\n\n while (num > 0) {\n num--; // Adjust for 0-based indexing\n suffix = String.fromCharCode(97 + (num % 26)) + suffix;\n num = Math.floor(num / 26);\n }\n\n return suffix;\n}\n\n/**\n * Generate ID with collision check\n * Appends a, b, c, ... suffix if the base ID already exists\n * @param item - CSL-JSON item\n * @param existingIds - Array of existing IDs\n * @returns Generated ID with collision handling\n */\nexport function generateIdWithCollisionCheck(item: CslItem, existingIds: string[]): string {\n const baseId = generateId(item);\n\n // Normalize existing IDs to lowercase for case-insensitive comparison\n const normalizedExistingIds = existingIds.map((id) => id.toLowerCase());\n\n // Check for collisions\n let candidate = baseId;\n let suffixIndex = 0;\n\n while (normalizedExistingIds.includes(candidate.toLowerCase())) {\n suffixIndex++;\n const suffix = generateSuffix(suffixIndex);\n candidate = `${baseId}${suffix}`;\n }\n\n return candidate;\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { CslCustom } from \"../csl-json/types\";\n\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/**\n * Validate if a string is a valid UUID v4\n */\nexport function isValidUuid(uuid: string): boolean {\n return UUID_REGEX.test(uuid);\n}\n\n/**\n * Generate a new UUID v4\n */\nexport function generateUuid(): string {\n return randomUUID();\n}\n\n/**\n * Generate a new ISO 8601 timestamp\n */\nexport function generateTimestamp(): string {\n return new Date().toISOString();\n}\n\n/**\n * Extract UUID from custom field\n */\nexport function extractUuidFromCustom(custom: CslCustom | undefined): string | null {\n if (!custom || !custom.uuid) {\n return null;\n }\n\n return isValidUuid(custom.uuid) ? custom.uuid : null;\n}\n\n/**\n * Ensure custom metadata has a valid UUID\n * Generates a new UUID if missing or invalid\n */\nfunction ensureUuid(custom: CslCustom | undefined): Partial<CslCustom> & { uuid: string } {\n const existingUuid = extractUuidFromCustom(custom);\n\n if (existingUuid && custom) {\n return custom as Partial<CslCustom> & { uuid: string };\n }\n\n const newUuid = generateUuid();\n return {\n ...custom,\n uuid: newUuid,\n };\n}\n\n/**\n * Ensure custom metadata has a valid created_at timestamp\n * Migrates from legacy timestamp field if needed\n * Generates a new timestamp if missing\n */\nfunction ensureCreatedAt(\n custom: Partial<CslCustom> & { uuid: string }\n): Partial<CslCustom> & { uuid: string; created_at: string } {\n // Already has created_at\n if (custom.created_at) {\n return custom as Partial<CslCustom> & { uuid: string; created_at: string };\n }\n\n // Legacy migration: move timestamp to created_at if timestamp exists but created_at doesn't\n if (custom.timestamp) {\n return {\n ...custom,\n created_at: custom.timestamp,\n };\n }\n\n // Generate new created_at\n const newTimestamp = generateTimestamp();\n return {\n ...custom,\n created_at: newTimestamp,\n };\n}\n\n/**\n * Ensure custom metadata has a valid timestamp (last modification time)\n * Defaults to created_at if missing\n */\nfunction ensureTimestamp(\n custom: Partial<CslCustom> & { uuid: string; created_at: string }\n): CslCustom {\n // Already has timestamp\n if (custom.timestamp) {\n return custom as CslCustom;\n }\n\n // Default to created_at (new item, not yet modified)\n return {\n ...custom,\n timestamp: custom.created_at,\n };\n}\n\n/**\n * Ensure custom metadata has valid UUID, created_at, and timestamp\n * Handles legacy migration from old timestamp-only format\n * Generates new values if missing or invalid\n */\nexport function ensureCustomMetadata(custom: CslCustom | undefined): CslCustom {\n const withUuid = ensureUuid(custom);\n const withCreatedAt = ensureCreatedAt(withUuid);\n const withTimestamp = ensureTimestamp(withCreatedAt);\n return withTimestamp;\n}\n","import type { CslItem } from \"./csl-json/types\";\nimport { generateIdWithCollisionCheck } from \"./identifier/generator\";\nimport { ensureCustomMetadata, extractUuidFromCustom } from \"./identifier/uuid\";\n\n/**\n * Options for creating a Reference\n */\nexport interface ReferenceCreateOptions {\n /** Existing IDs to check for collision */\n existingIds?: Set<string>;\n}\n\n/**\n * Reference entity wrapping a CSL-JSON item\n */\nexport class Reference {\n private item: CslItem;\n private uuid: string;\n\n constructor(item: CslItem) {\n // Ensure UUID and timestamp are present and valid in custom field\n const customMetadata = ensureCustomMetadata(item.custom);\n this.item = { ...item, custom: customMetadata };\n\n // Extract UUID from the custom field\n const extractedUuid = extractUuidFromCustom(customMetadata);\n if (!extractedUuid) {\n throw new Error(\"Failed to extract UUID after ensureCustomMetadata\");\n }\n this.uuid = extractedUuid;\n }\n\n /**\n * Factory method to create a Reference with UUID and ID generation\n */\n static create(item: CslItem, options?: ReferenceCreateOptions): Reference {\n const existingIds = options?.existingIds || new Set<string>();\n\n // Generate ID if not provided or empty\n let updatedItem = item;\n if (!item.id || item.id.trim() === \"\") {\n const generatedId = generateIdWithCollisionCheck(item, Array.from(existingIds));\n updatedItem = { ...item, id: generatedId };\n }\n\n return new Reference(updatedItem);\n }\n\n /**\n * Get the underlying CSL-JSON item\n */\n getItem(): CslItem {\n return this.item;\n }\n\n /**\n * Get the UUID (internal stable identifier)\n */\n getUuid(): string {\n return this.uuid;\n }\n\n /**\n * Get the ID (Pandoc citation key / BibTeX-key)\n */\n getId(): string {\n return this.item.id;\n }\n\n /**\n * Get the title\n */\n getTitle(): string | undefined {\n return this.item.title;\n }\n\n /**\n * Get the authors\n */\n getAuthors(): CslItem[\"author\"] {\n return this.item.author;\n }\n\n /**\n * Get the year from issued date\n */\n getYear(): number | undefined {\n const issued = this.item.issued;\n if (!issued || !issued[\"date-parts\"] || issued[\"date-parts\"].length === 0) {\n return undefined;\n }\n const firstDate = issued[\"date-parts\"][0];\n return firstDate && firstDate.length > 0 ? firstDate[0] : undefined;\n }\n\n /**\n * Get the DOI\n */\n getDoi(): string | undefined {\n return this.item.DOI;\n }\n\n /**\n * Get the PMID\n */\n getPmid(): string | undefined {\n return this.item.PMID;\n }\n\n /**\n * Get the PMCID\n */\n getPmcid(): string | undefined {\n return this.item.PMCID;\n }\n\n /**\n * Get the URL\n */\n getUrl(): string | undefined {\n return this.item.URL;\n }\n\n /**\n * Get the keyword\n */\n getKeyword(): string[] | undefined {\n return this.item.keyword;\n }\n\n /**\n * Get additional URLs from custom metadata\n */\n getAdditionalUrls(): string[] | undefined {\n return this.item.custom?.additional_urls;\n }\n\n /**\n * Get the creation timestamp from custom metadata (immutable)\n */\n getCreatedAt(): string {\n if (!this.item.custom?.created_at) {\n throw new Error(\"created_at is missing from custom metadata\");\n }\n return this.item.custom.created_at;\n }\n\n /**\n * Get the last modification timestamp from custom metadata\n */\n getTimestamp(): string {\n if (!this.item.custom?.timestamp) {\n throw new Error(\"timestamp is missing from custom metadata\");\n }\n return this.item.custom.timestamp;\n }\n\n /**\n * Update the timestamp to current time\n * Call this whenever the reference is modified\n */\n touch(): void {\n if (!this.item.custom) {\n throw new Error(\"custom metadata is missing\");\n }\n this.item.custom.timestamp = new Date().toISOString();\n }\n\n /**\n * Get the type\n */\n getType(): string {\n return this.item.type;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { createReadStream } from \"node:fs\";\n\n/**\n * Compute SHA-256 hash of a string\n */\nexport function computeHash(input: string): string {\n return createHash(\"sha256\").update(input, \"utf-8\").digest(\"hex\");\n}\n\n/**\n * Compute SHA-256 hash of a file\n */\nexport async function computeFileHash(filePath: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = createHash(\"sha256\");\n const stream = createReadStream(filePath);\n\n stream.on(\"data\", (chunk) => hash.update(chunk));\n stream.on(\"end\", () => resolve(hash.digest(\"hex\")));\n stream.on(\"error\", (error) => reject(error));\n });\n}\n","import { readFile } from \"node:fs/promises\";\nimport { ensureCustomMetadata } from \"../identifier/uuid\";\nimport { type CslLibrary, CslLibrarySchema } from \"./types\";\n\n/**\n * Convert keyword field from semicolon-separated string to array\n * @param keyword - Semicolon-separated string or undefined\n * @returns Array of keywords or undefined\n */\nfunction parseKeyword(keyword: unknown): string[] | undefined {\n if (typeof keyword !== \"string\") {\n return undefined;\n }\n\n if (keyword.trim() === \"\") {\n return undefined;\n }\n\n const keywords = keyword\n .split(\";\")\n .map((k) => k.trim())\n .filter((k) => k !== \"\");\n\n return keywords.length > 0 ? keywords : undefined;\n}\n\n/**\n * Parse a CSL-JSON file and ensure all entries have valid UUIDs and timestamps\n * @param filePath - Path to the CSL-JSON file\n * @returns Array of CSL-JSON items with guaranteed UUIDs and timestamps\n * @throws Error if file cannot be read or JSON is invalid\n */\nexport async function parseCslJson(filePath: string): Promise<CslLibrary> {\n // Read file\n const content = await readFile(filePath, \"utf-8\");\n\n // Parse JSON\n let rawData: unknown;\n try {\n rawData = JSON.parse(content);\n } catch (error) {\n throw new Error(\n `Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n\n // Convert keyword fields from string to array before validation\n if (Array.isArray(rawData)) {\n rawData = rawData.map((item: unknown) => {\n if (item && typeof item === \"object\" && \"keyword\" in item) {\n const itemWithKeyword = item as Record<string, unknown>;\n return {\n ...itemWithKeyword,\n keyword: parseKeyword(itemWithKeyword.keyword),\n };\n }\n return item;\n });\n }\n\n // Validate with zod\n const parseResult = CslLibrarySchema.safeParse(rawData);\n\n if (!parseResult.success) {\n throw new Error(`Invalid CSL-JSON structure: ${parseResult.error.message}`);\n }\n\n const library = parseResult.data;\n\n // Ensure all entries have valid UUIDs and timestamps\n const processedLibrary: CslLibrary = library.map((item) => {\n const updatedCustom = ensureCustomMetadata(item.custom);\n\n return {\n ...item,\n custom: updatedCustom,\n };\n });\n\n return processedLibrary;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { CslLibrary } from \"./types\";\n\n/**\n * Convert keyword array to semicolon-separated string\n * @param keywords - Array of keywords or undefined\n * @returns Semicolon-separated string or undefined\n */\nfunction serializeKeyword(keywords: string[] | undefined): string | undefined {\n if (!keywords || keywords.length === 0) {\n return undefined;\n }\n\n return keywords.join(\"; \");\n}\n\n/**\n * Serialize a CSL-JSON library to a formatted JSON string\n * @param library - CSL-JSON library (array of items)\n * @returns Formatted JSON string with 2-space indentation\n */\nexport function serializeCslJson(library: CslLibrary): string {\n // Convert keyword arrays to semicolon-separated strings\n const libraryForJson = library.map((item) => {\n const { keyword, ...rest } = item;\n const serializedKeyword = serializeKeyword(keyword);\n\n if (serializedKeyword === undefined) {\n return rest;\n }\n\n return {\n ...rest,\n keyword: serializedKeyword,\n };\n });\n\n return JSON.stringify(libraryForJson, null, 2);\n}\n\n/**\n * Write a CSL-JSON library to a file\n * @param filePath - Path to write the CSL-JSON file\n * @param library - CSL-JSON library to write\n * @throws Error if file cannot be written\n */\nexport async function writeCslJson(filePath: string, library: CslLibrary): Promise<void> {\n // Ensure parent directory exists\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n\n // Serialize and write\n const content = serializeCslJson(library);\n await writeFile(filePath, content, \"utf-8\");\n}\n","import { computeFileHash } from \"../utils/hash\";\nimport { parseCslJson } from \"./csl-json/parser\";\nimport { writeCslJson } from \"./csl-json/serializer\";\nimport type { CslItem } from \"./csl-json/types\";\nimport { Reference } from \"./reference\";\n\n/**\n * Options for update operations\n */\nexport interface UpdateOptions {\n /** How to handle ID collision: 'fail' (default) or 'suffix' */\n onIdCollision?: \"fail\" | \"suffix\";\n}\n\n/**\n * Result of an update operation\n */\nexport interface UpdateResult {\n /** Whether the update was successful */\n updated: boolean;\n /** True if ID collision occurred (only when updated=false and onIdCollision='fail') */\n idCollision?: boolean;\n /** True if the ID was changed due to collision resolution */\n idChanged?: boolean;\n /** The new ID after collision resolution (only when idChanged=true) */\n newId?: string;\n}\n\n/**\n * Library manager for CSL-JSON references\n */\nexport class Library {\n private filePath: string;\n private references: Reference[] = [];\n private currentHash: string | null = null;\n\n // Indices for fast lookup\n private uuidIndex: Map<string, Reference> = new Map();\n private idIndex: Map<string, Reference> = new Map();\n private doiIndex: Map<string, Reference> = new Map();\n private pmidIndex: Map<string, Reference> = new Map();\n\n private constructor(filePath: string, items: CslItem[]) {\n this.filePath = filePath;\n\n // Create references and build indices\n for (const item of items) {\n const ref = new Reference(item);\n this.references.push(ref);\n this.addToIndices(ref);\n }\n }\n\n /**\n * Load library from file\n */\n static async load(filePath: string): Promise<Library> {\n const items = await parseCslJson(filePath);\n const library = new Library(filePath, items);\n // Compute and store file hash after loading\n library.currentHash = await computeFileHash(filePath);\n return library;\n }\n\n /**\n * Save library to file\n */\n async save(): Promise<void> {\n const items = this.references.map((ref) => ref.getItem());\n await writeCslJson(this.filePath, items);\n // Update file hash after saving\n this.currentHash = await computeFileHash(this.filePath);\n }\n\n /**\n * Add a reference to the library\n */\n add(item: CslItem): void {\n // Collect existing IDs for collision check\n const existingIds = new Set(this.references.map((ref) => ref.getId()));\n\n // Create reference with collision check\n const ref = Reference.create(item, { existingIds });\n\n // Add to library\n this.references.push(ref);\n this.addToIndices(ref);\n }\n\n /**\n * Remove a reference by UUID\n */\n removeByUuid(uuid: string): boolean {\n const ref = this.uuidIndex.get(uuid);\n if (!ref) {\n return false;\n }\n\n return this.removeReference(ref);\n }\n\n /**\n * Remove a reference by ID\n */\n removeById(id: string): boolean {\n const ref = this.idIndex.get(id);\n if (!ref) {\n return false;\n }\n\n return this.removeReference(ref);\n }\n\n /**\n * Update a reference by UUID.\n * @param uuid - The UUID of the reference to update\n * @param updates - Partial updates to apply to the reference\n * @returns true if the reference was found and updated, false otherwise\n */\n updateByUuid(uuid: string, updates: Partial<CslItem>, options: UpdateOptions = {}): UpdateResult {\n const ref = this.uuidIndex.get(uuid);\n if (!ref) {\n return { updated: false };\n }\n\n return this.updateReference(ref, updates, options);\n }\n\n /**\n * Update a reference by ID.\n * @param id - The ID of the reference to update\n * @param updates - Partial updates to apply to the reference\n * @returns true if the reference was found and updated, false otherwise\n */\n updateById(id: string, updates: Partial<CslItem>, options: UpdateOptions = {}): UpdateResult {\n const ref = this.idIndex.get(id);\n if (!ref) {\n return { updated: false };\n }\n\n return this.updateReference(ref, updates, options);\n }\n\n /**\n * Find a reference by UUID\n */\n findByUuid(uuid: string): Reference | undefined {\n return this.uuidIndex.get(uuid);\n }\n\n /**\n * Find a reference by ID\n */\n findById(id: string): Reference | undefined {\n return this.idIndex.get(id);\n }\n\n /**\n * Find a reference by DOI\n */\n findByDoi(doi: string): Reference | undefined {\n return this.doiIndex.get(doi);\n }\n\n /**\n * Find a reference by PMID\n */\n findByPmid(pmid: string): Reference | undefined {\n return this.pmidIndex.get(pmid);\n }\n\n /**\n * Get all references\n */\n getAll(): Reference[] {\n return [...this.references];\n }\n\n /**\n * Get the file path\n */\n getFilePath(): string {\n return this.filePath;\n }\n\n /**\n * Get the current file hash\n * Returns null if the library has not been loaded or saved yet\n */\n getCurrentHash(): string | null {\n return this.currentHash;\n }\n\n /**\n * Add reference to all indices\n */\n private addToIndices(ref: Reference): void {\n // UUID index\n this.uuidIndex.set(ref.getUuid(), ref);\n\n // ID index\n this.idIndex.set(ref.getId(), ref);\n\n // DOI index\n const doi = ref.getDoi();\n if (doi) {\n this.doiIndex.set(doi, ref);\n }\n\n // PMID index\n const pmid = ref.getPmid();\n if (pmid) {\n this.pmidIndex.set(pmid, ref);\n }\n }\n\n /**\n * Remove reference from all indices and array\n */\n private removeReference(ref: Reference): boolean {\n const index = this.references.indexOf(ref);\n if (index === -1) {\n return false;\n }\n this.references.splice(index, 1);\n this.removeFromIndices(ref);\n return true;\n }\n\n /**\n * Update a reference with partial updates.\n * Preserves uuid and created_at, updates timestamp.\n */\n private updateReference(\n ref: Reference,\n updates: Partial<CslItem>,\n options: UpdateOptions = {}\n ): UpdateResult {\n const index = this.references.indexOf(ref);\n if (index === -1) {\n return { updated: false };\n }\n\n const existingItem = ref.getItem();\n const currentId = ref.getId();\n const { newId, idChanged, collision } = this.resolveNewId(\n updates.id ?? existingItem.id,\n currentId,\n options\n );\n\n if (collision) {\n return { updated: false, idCollision: true };\n }\n\n const updatedItem = this.buildUpdatedItem(existingItem, updates, newId);\n\n // Remove old reference from indices\n this.removeFromIndices(ref);\n\n // Create new reference and replace in array\n const newRef = new Reference(updatedItem);\n this.references[index] = newRef;\n this.addToIndices(newRef);\n\n const result: UpdateResult = { updated: true };\n if (idChanged) {\n result.idChanged = true;\n result.newId = newId;\n }\n return result;\n }\n\n /**\n * Resolve the new ID, handling collisions based on options.\n */\n private resolveNewId(\n requestedId: string,\n currentId: string,\n options: UpdateOptions\n ): { newId: string; idChanged: boolean; collision: boolean } {\n if (requestedId === currentId) {\n return { newId: requestedId, idChanged: false, collision: false };\n }\n\n const conflictingRef = this.idIndex.get(requestedId);\n if (!conflictingRef) {\n return { newId: requestedId, idChanged: false, collision: false };\n }\n\n const onIdCollision = options.onIdCollision ?? \"fail\";\n if (onIdCollision === \"fail\") {\n return { newId: requestedId, idChanged: false, collision: true };\n }\n\n // onIdCollision === \"suffix\": resolve by adding suffix\n const existingIds = new Set(this.references.map((r) => r.getId()));\n existingIds.delete(currentId);\n const resolvedId = this.resolveIdCollision(requestedId, existingIds);\n return { newId: resolvedId, idChanged: true, collision: false };\n }\n\n /**\n * Build the updated CslItem, preserving uuid and created_at.\n */\n private buildUpdatedItem(\n existingItem: CslItem,\n updates: Partial<CslItem>,\n newId: string\n ): CslItem {\n return {\n ...existingItem,\n ...updates,\n id: newId,\n type: updates.type ?? existingItem.type,\n custom: {\n ...(existingItem.custom || {}),\n ...(updates.custom || {}),\n uuid: existingItem.custom?.uuid || \"\",\n created_at: existingItem.custom?.created_at || new Date().toISOString(),\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n /**\n * Remove a reference from all indices.\n */\n private removeFromIndices(ref: Reference): void {\n this.uuidIndex.delete(ref.getUuid());\n this.idIndex.delete(ref.getId());\n\n const doi = ref.getDoi();\n if (doi) {\n this.doiIndex.delete(doi);\n }\n\n const pmid = ref.getPmid();\n if (pmid) {\n this.pmidIndex.delete(pmid);\n }\n }\n\n /**\n * Generate an alphabetic suffix for ID collision resolution.\n * 0 -> 'a', 1 -> 'b', ..., 25 -> 'z', 26 -> 'aa', etc.\n */\n private generateSuffix(index: number): string {\n const alphabet = \"abcdefghijklmnopqrstuvwxyz\";\n let suffix = \"\";\n let n = index;\n\n do {\n suffix = alphabet[n % 26] + suffix;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n\n return suffix;\n }\n\n /**\n * Resolve ID collision by appending alphabetic suffix.\n */\n private resolveIdCollision(baseId: string, existingIds: Set<string>): string {\n if (!existingIds.has(baseId)) {\n return baseId;\n }\n\n let index = 0;\n let newId: string;\n\n do {\n const suffix = this.generateSuffix(index);\n newId = `${baseId}${suffix}`;\n index++;\n } while (existingIds.has(newId));\n\n return newId;\n }\n}\n","/**\n * Configuration schema using Zod\n */\n\nimport { z } from \"zod\";\n\n/**\n * Log level schema\n */\nexport const logLevelSchema = z.enum([\"silent\", \"info\", \"debug\"]);\n\n/**\n * Backup configuration schema\n */\nexport const backupConfigSchema = z.object({\n maxGenerations: z.number().int().positive(),\n maxAgeDays: z.number().int().positive(),\n directory: z.string().min(1),\n});\n\n/**\n * File watching configuration schema\n */\nexport const watchConfigSchema = z.object({\n enabled: z.boolean(),\n debounceMs: z.number().int().nonnegative(),\n pollIntervalMs: z.number().int().positive(),\n retryIntervalMs: z.number().int().positive(),\n maxRetries: z.number().int().nonnegative(),\n});\n\n/**\n * Server configuration schema\n */\nexport const serverConfigSchema = z.object({\n autoStart: z.boolean(),\n autoStopMinutes: z.number().int().nonnegative(),\n});\n\n/**\n * Citation format schema\n */\nexport const citationFormatSchema = z.enum([\"text\", \"html\", \"rtf\"]);\n\n/**\n * Citation configuration schema\n */\nexport const citationConfigSchema = z.object({\n defaultStyle: z.string(),\n cslDirectory: z.array(z.string()),\n defaultLocale: z.string(),\n defaultFormat: citationFormatSchema,\n});\n\n/**\n * PubMed API configuration schema\n */\nexport const pubmedConfigSchema = z.object({\n email: z.string().optional(),\n apiKey: z.string().optional(),\n});\n\n/**\n * Fulltext storage configuration schema\n */\nexport const fulltextConfigSchema = z.object({\n directory: z.string().min(1),\n});\n\n/**\n * Complete configuration schema\n */\nexport const configSchema = z.object({\n library: z.string().min(1),\n logLevel: logLevelSchema,\n backup: backupConfigSchema,\n watch: watchConfigSchema,\n server: serverConfigSchema,\n citation: citationConfigSchema,\n pubmed: pubmedConfigSchema,\n fulltext: fulltextConfigSchema,\n});\n\n/**\n * Partial configuration schema (for TOML files)\n * Supports both camelCase and snake_case field names\n */\nexport const partialConfigSchema = z\n .object({\n library: z.string().min(1).optional(),\n logLevel: logLevelSchema.optional(),\n log_level: logLevelSchema.optional(), // snake_case support\n backup: z\n .object({\n maxGenerations: z.number().int().positive().optional(),\n max_generations: z.number().int().positive().optional(),\n maxAgeDays: z.number().int().positive().optional(),\n max_age_days: z.number().int().positive().optional(),\n directory: z.string().min(1).optional(),\n })\n .optional(),\n watch: z\n .object({\n enabled: z.boolean().optional(),\n debounceMs: z.number().int().nonnegative().optional(),\n debounce_ms: z.number().int().nonnegative().optional(),\n pollIntervalMs: z.number().int().positive().optional(),\n poll_interval_ms: z.number().int().positive().optional(),\n retryIntervalMs: z.number().int().positive().optional(),\n retry_interval_ms: z.number().int().positive().optional(),\n maxRetries: z.number().int().nonnegative().optional(),\n max_retries: z.number().int().nonnegative().optional(),\n })\n .optional(),\n server: z\n .object({\n autoStart: z.boolean().optional(),\n auto_start: z.boolean().optional(),\n autoStopMinutes: z.number().int().nonnegative().optional(),\n auto_stop_minutes: z.number().int().nonnegative().optional(),\n })\n .optional(),\n citation: z\n .object({\n defaultStyle: z.string().optional(),\n default_style: z.string().optional(),\n cslDirectory: z.union([z.string(), z.array(z.string())]).optional(),\n csl_directory: z.union([z.string(), z.array(z.string())]).optional(),\n defaultLocale: z.string().optional(),\n default_locale: z.string().optional(),\n defaultFormat: citationFormatSchema.optional(),\n default_format: citationFormatSchema.optional(),\n })\n .optional(),\n pubmed: z\n .object({\n email: z.string().optional(),\n apiKey: z.string().optional(),\n api_key: z.string().optional(),\n })\n .optional(),\n fulltext: z\n .object({\n directory: z.string().min(1).optional(),\n })\n .optional(),\n })\n .passthrough(); // Allow unknown fields in TOML files\n\n/**\n * Inferred types from schemas\n */\nexport type LogLevel = z.infer<typeof logLevelSchema>;\nexport type BackupConfig = z.infer<typeof backupConfigSchema>;\nexport type WatchConfig = z.infer<typeof watchConfigSchema>;\nexport type ServerConfig = z.infer<typeof serverConfigSchema>;\nexport type CitationFormat = z.infer<typeof citationFormatSchema>;\nexport type CitationConfig = z.infer<typeof citationConfigSchema>;\nexport type PubmedConfig = z.infer<typeof pubmedConfigSchema>;\nexport type FulltextConfig = z.infer<typeof fulltextConfigSchema>;\nexport type Config = z.infer<typeof configSchema>;\nexport type PartialConfig = z.infer<typeof partialConfigSchema>;\n\n/**\n * Deep partial type for Config\n */\nexport type DeepPartialConfig = {\n library?: string;\n logLevel?: LogLevel;\n backup?: Partial<BackupConfig>;\n watch?: Partial<WatchConfig>;\n server?: Partial<ServerConfig>;\n citation?: Partial<CitationConfig>;\n pubmed?: Partial<PubmedConfig>;\n fulltext?: Partial<FulltextConfig>;\n};\n\n/**\n * Normalize backup configuration from snake_case to camelCase\n */\nfunction normalizeBackupConfig(\n backup: Partial<{\n maxGenerations?: number;\n max_generations?: number;\n maxAgeDays?: number;\n max_age_days?: number;\n directory?: string;\n }>\n): Partial<BackupConfig> | undefined {\n const normalized: Partial<BackupConfig> = {};\n\n const maxGenerations = backup.maxGenerations ?? backup.max_generations;\n if (maxGenerations !== undefined) {\n normalized.maxGenerations = maxGenerations;\n }\n\n const maxAgeDays = backup.maxAgeDays ?? backup.max_age_days;\n if (maxAgeDays !== undefined) {\n normalized.maxAgeDays = maxAgeDays;\n }\n\n if (backup.directory !== undefined) {\n normalized.directory = backup.directory;\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\n/**\n * Normalize watch configuration from snake_case to camelCase\n */\nfunction normalizeWatchConfig(\n watch: Partial<{\n enabled?: boolean;\n debounceMs?: number;\n debounce_ms?: number;\n pollIntervalMs?: number;\n poll_interval_ms?: number;\n retryIntervalMs?: number;\n retry_interval_ms?: number;\n maxRetries?: number;\n max_retries?: number;\n }>\n): Partial<WatchConfig> | undefined {\n const normalized: Partial<WatchConfig> = {};\n\n if (watch.enabled !== undefined) {\n normalized.enabled = watch.enabled;\n }\n\n const debounceMs = watch.debounceMs ?? watch.debounce_ms;\n if (debounceMs !== undefined) {\n normalized.debounceMs = debounceMs;\n }\n\n const pollIntervalMs = watch.pollIntervalMs ?? watch.poll_interval_ms;\n if (pollIntervalMs !== undefined) {\n normalized.pollIntervalMs = pollIntervalMs;\n }\n\n const retryIntervalMs = watch.retryIntervalMs ?? watch.retry_interval_ms;\n if (retryIntervalMs !== undefined) {\n normalized.retryIntervalMs = retryIntervalMs;\n }\n\n const maxRetries = watch.maxRetries ?? watch.max_retries;\n if (maxRetries !== undefined) {\n normalized.maxRetries = maxRetries;\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\n/**\n * Normalize server configuration from snake_case to camelCase\n */\nfunction normalizeServerConfig(\n server: Partial<{\n autoStart?: boolean;\n auto_start?: boolean;\n autoStopMinutes?: number;\n auto_stop_minutes?: number;\n }>\n): Partial<ServerConfig> | undefined {\n const normalized: Partial<ServerConfig> = {};\n\n const autoStart = server.autoStart ?? server.auto_start;\n if (autoStart !== undefined) {\n normalized.autoStart = autoStart;\n }\n\n const autoStopMinutes = server.autoStopMinutes ?? server.auto_stop_minutes;\n if (autoStopMinutes !== undefined) {\n normalized.autoStopMinutes = autoStopMinutes;\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\n/**\n * Normalize citation configuration from snake_case to camelCase\n */\nfunction normalizeCitationConfig(\n citation: Partial<{\n defaultStyle?: string;\n default_style?: string;\n cslDirectory?: string | string[];\n csl_directory?: string | string[];\n defaultLocale?: string;\n default_locale?: string;\n defaultFormat?: CitationFormat;\n default_format?: CitationFormat;\n }>\n): Partial<CitationConfig> | undefined {\n const normalized: Partial<CitationConfig> = {};\n\n const defaultStyle = citation.defaultStyle ?? citation.default_style;\n if (defaultStyle !== undefined) {\n normalized.defaultStyle = defaultStyle;\n }\n\n const cslDirectory = citation.cslDirectory ?? citation.csl_directory;\n if (cslDirectory !== undefined) {\n // Normalize to array: string -> [string]\n normalized.cslDirectory = Array.isArray(cslDirectory) ? cslDirectory : [cslDirectory];\n }\n\n const defaultLocale = citation.defaultLocale ?? citation.default_locale;\n if (defaultLocale !== undefined) {\n normalized.defaultLocale = defaultLocale;\n }\n\n const defaultFormat = citation.defaultFormat ?? citation.default_format;\n if (defaultFormat !== undefined) {\n normalized.defaultFormat = defaultFormat;\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\n/**\n * Normalize pubmed configuration from snake_case to camelCase\n */\nfunction normalizePubmedConfig(\n pubmed: Partial<{\n email?: string;\n apiKey?: string;\n api_key?: string;\n }>\n): Partial<PubmedConfig> | undefined {\n const normalized: Partial<PubmedConfig> = {};\n\n if (pubmed.email !== undefined) {\n normalized.email = pubmed.email;\n }\n\n const apiKey = pubmed.apiKey ?? pubmed.api_key;\n if (apiKey !== undefined) {\n normalized.apiKey = apiKey;\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\n/**\n * Normalize snake_case fields to camelCase\n */\nexport function normalizePartialConfig(partial: PartialConfig): DeepPartialConfig {\n const normalized: DeepPartialConfig = {};\n\n // Library\n if (partial.library !== undefined) {\n normalized.library = partial.library;\n }\n\n // Log level (prefer camelCase, fallback to snake_case)\n const logLevel = partial.logLevel ?? partial.log_level;\n if (logLevel !== undefined) {\n normalized.logLevel = logLevel;\n }\n\n // Backup\n const backup =\n partial.backup !== undefined\n ? normalizeBackupConfig(partial.backup as Parameters<typeof normalizeBackupConfig>[0])\n : undefined;\n if (backup) {\n normalized.backup = backup;\n }\n\n // Watch\n const watch =\n partial.watch !== undefined\n ? normalizeWatchConfig(partial.watch as Parameters<typeof normalizeWatchConfig>[0])\n : undefined;\n if (watch) {\n normalized.watch = watch;\n }\n\n // Server\n const server =\n partial.server !== undefined\n ? normalizeServerConfig(partial.server as Parameters<typeof normalizeServerConfig>[0])\n : undefined;\n if (server) {\n normalized.server = server;\n }\n\n // Citation\n const citation =\n partial.citation !== undefined\n ? normalizeCitationConfig(partial.citation as Parameters<typeof normalizeCitationConfig>[0])\n : undefined;\n if (citation) {\n normalized.citation = citation;\n }\n\n // PubMed\n const pubmed =\n partial.pubmed !== undefined\n ? normalizePubmedConfig(partial.pubmed as Parameters<typeof normalizePubmedConfig>[0])\n : undefined;\n if (pubmed) {\n normalized.pubmed = pubmed;\n }\n\n // Fulltext\n const fulltext =\n partial.fulltext !== undefined ? normalizeFulltextConfig(partial.fulltext) : undefined;\n if (fulltext) {\n normalized.fulltext = fulltext;\n }\n\n return normalized;\n}\n\n/**\n * Normalize fulltext configuration\n */\nfunction normalizeFulltextConfig(fulltext: {\n directory?: string | undefined;\n}): Partial<FulltextConfig> | undefined {\n const normalized: Partial<FulltextConfig> = {};\n\n if (fulltext.directory !== undefined) {\n normalized.directory = fulltext.directory;\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n","/**\n * Default configuration values\n */\n\nimport { tmpdir } from \"node:os\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Config } from \"./schema.js\";\n\n/**\n * Get the default backup directory\n * Uses $TMPDIR/reference-manager/backups/\n */\nexport function getDefaultBackupDirectory(): string {\n return join(tmpdir(), \"reference-manager\", \"backups\");\n}\n\n/**\n * Get the default library path\n * Uses ~/.reference-manager/csl.library.json\n */\nexport function getDefaultLibraryPath(): string {\n return join(homedir(), \".reference-manager\", \"csl.library.json\");\n}\n\n/**\n * Get the default user config path\n * Uses ~/.reference-manager/config.toml\n */\nexport function getDefaultUserConfigPath(): string {\n return join(homedir(), \".reference-manager\", \"config.toml\");\n}\n\n/**\n * Get the default current directory config filename\n * Uses .reference-manager.config.toml\n */\nexport function getDefaultCurrentDirConfigFilename(): string {\n return \".reference-manager.config.toml\";\n}\n\n/**\n * Get the default CSL directory\n * Uses ~/.reference-manager/csl/\n */\nexport function getDefaultCslDirectory(): string {\n return join(homedir(), \".reference-manager\", \"csl\");\n}\n\n/**\n * Get the default fulltext directory\n * Uses ~/.reference-manager/fulltext/\n */\nexport function getDefaultFulltextDirectory(): string {\n return join(homedir(), \".reference-manager\", \"fulltext\");\n}\n\n/**\n * Default configuration\n */\nexport const defaultConfig: Config = {\n library: getDefaultLibraryPath(),\n logLevel: \"info\",\n backup: {\n maxGenerations: 50,\n maxAgeDays: 365,\n directory: getDefaultBackupDirectory(),\n },\n watch: {\n enabled: true,\n debounceMs: 500,\n pollIntervalMs: 5000,\n retryIntervalMs: 200,\n maxRetries: 10,\n },\n server: {\n autoStart: false,\n autoStopMinutes: 0,\n },\n citation: {\n defaultStyle: \"apa\",\n cslDirectory: [getDefaultCslDirectory()],\n defaultLocale: \"en-US\",\n defaultFormat: \"text\",\n },\n pubmed: {\n email: undefined,\n apiKey: undefined,\n },\n fulltext: {\n directory: getDefaultFulltextDirectory(),\n },\n};\n","/**\n * Configuration loader\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { parse as parseTOML } from \"@iarna/toml\";\nimport {\n defaultConfig,\n getDefaultCurrentDirConfigFilename,\n getDefaultUserConfigPath,\n} from \"./defaults.js\";\nimport {\n type Config,\n type DeepPartialConfig,\n type PartialConfig,\n configSchema,\n normalizePartialConfig,\n partialConfigSchema,\n} from \"./schema.js\";\n\n/**\n * Options for loading configuration\n */\nexport interface LoadConfigOptions {\n /** Current working directory (default: process.cwd()) */\n cwd?: string;\n /** User config path (default: ~/.reference-manager/config.toml) */\n userConfigPath?: string;\n /** CLI argument overrides */\n overrides?: Partial<Config>;\n}\n\n/**\n * Load and parse a TOML config file\n */\nfunction loadTOMLFile(path: string): PartialConfig | null {\n if (!existsSync(path)) {\n return null;\n }\n\n try {\n const content = readFileSync(path, \"utf-8\");\n const parsed = parseTOML(content);\n\n // Validate with partial schema\n const validated = partialConfigSchema.parse(parsed);\n return validated;\n } catch (error) {\n throw new Error(\n `Failed to load config from ${path}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Merge partial configurations\n * Later configs override earlier ones\n */\nfunction mergeConfigs(\n base: DeepPartialConfig,\n ...overrides: (DeepPartialConfig | null | undefined)[]\n): DeepPartialConfig {\n const result: DeepPartialConfig = { ...base };\n\n const sectionKeys = [\"backup\", \"watch\", \"server\", \"citation\", \"pubmed\", \"fulltext\"] as const;\n\n for (const override of overrides) {\n if (!override) continue;\n\n // Merge top-level primitive fields\n if (override.library !== undefined) {\n result.library = override.library;\n }\n if (override.logLevel !== undefined) {\n result.logLevel = override.logLevel;\n }\n\n // Merge section configs\n for (const key of sectionKeys) {\n if (override[key] !== undefined) {\n result[key] = {\n ...result[key],\n ...override[key],\n };\n }\n }\n }\n\n return result;\n}\n\n/**\n * Fill missing fields with defaults\n */\nfunction fillDefaults(partial: DeepPartialConfig): Config {\n return {\n library: partial.library ?? defaultConfig.library,\n logLevel: partial.logLevel ?? defaultConfig.logLevel,\n backup: {\n maxGenerations: partial.backup?.maxGenerations ?? defaultConfig.backup.maxGenerations,\n maxAgeDays: partial.backup?.maxAgeDays ?? defaultConfig.backup.maxAgeDays,\n directory: partial.backup?.directory ?? defaultConfig.backup.directory,\n },\n watch: {\n enabled: partial.watch?.enabled ?? defaultConfig.watch.enabled,\n debounceMs: partial.watch?.debounceMs ?? defaultConfig.watch.debounceMs,\n pollIntervalMs: partial.watch?.pollIntervalMs ?? defaultConfig.watch.pollIntervalMs,\n retryIntervalMs: partial.watch?.retryIntervalMs ?? defaultConfig.watch.retryIntervalMs,\n maxRetries: partial.watch?.maxRetries ?? defaultConfig.watch.maxRetries,\n },\n server: {\n autoStart: partial.server?.autoStart ?? defaultConfig.server.autoStart,\n autoStopMinutes: partial.server?.autoStopMinutes ?? defaultConfig.server.autoStopMinutes,\n },\n citation: fillCitationDefaults(partial.citation),\n pubmed: fillPubmedDefaults(partial.pubmed),\n fulltext: fillFulltextDefaults(partial.fulltext),\n };\n}\n\n/**\n * Fill citation config with defaults\n */\nfunction fillCitationDefaults(partial: DeepPartialConfig[\"citation\"]): Config[\"citation\"] {\n return {\n defaultStyle: partial?.defaultStyle ?? defaultConfig.citation.defaultStyle,\n cslDirectory: partial?.cslDirectory ?? defaultConfig.citation.cslDirectory,\n defaultLocale: partial?.defaultLocale ?? defaultConfig.citation.defaultLocale,\n defaultFormat: partial?.defaultFormat ?? defaultConfig.citation.defaultFormat,\n };\n}\n\n/**\n * Fill pubmed config with defaults\n * Environment variables take priority over config file values\n */\nfunction fillPubmedDefaults(partial: DeepPartialConfig[\"pubmed\"]): Config[\"pubmed\"] {\n // Environment variables take priority\n const email = process.env.PUBMED_EMAIL ?? partial?.email ?? defaultConfig.pubmed.email;\n const apiKey = process.env.PUBMED_API_KEY ?? partial?.apiKey ?? defaultConfig.pubmed.apiKey;\n\n return {\n email,\n apiKey,\n };\n}\n\n/**\n * Expand ~ to home directory\n */\nfunction expandTilde(path: string): string {\n if (path.startsWith(\"~/\")) {\n return join(homedir(), path.slice(2));\n }\n return path;\n}\n\n/**\n * Fill fulltext config with defaults\n *\n * Priority:\n * 1. Environment variable REFERENCE_MANAGER_FULLTEXT_DIR\n * 2. Config file setting\n * 3. Default value\n */\nfunction fillFulltextDefaults(partial: DeepPartialConfig[\"fulltext\"]): Config[\"fulltext\"] {\n const envDir = process.env.REFERENCE_MANAGER_FULLTEXT_DIR;\n const directory = envDir ?? partial?.directory ?? defaultConfig.fulltext.directory;\n return {\n directory: expandTilde(directory),\n };\n}\n\n/**\n * Load configuration from multiple sources\n *\n * Priority (highest to lowest):\n * 1. CLI argument overrides\n * 2. Current directory config (.reference-manager.config.toml)\n * 3. Environment variable (REFERENCE_MANAGER_CONFIG)\n * 4. User config (~/.reference-manager/config.toml)\n * 5. Default values\n */\nexport function loadConfig(options: LoadConfigOptions = {}): Config {\n const cwd = options.cwd ?? process.cwd();\n const userConfigPath = options.userConfigPath ?? getDefaultUserConfigPath();\n\n // 1. Load user config (lowest priority)\n const userConfig = loadTOMLFile(userConfigPath);\n\n // 2. Load environment variable config\n const envConfigPath = process.env.REFERENCE_MANAGER_CONFIG;\n const envConfig = envConfigPath ? loadTOMLFile(envConfigPath) : null;\n\n // 3. Load current directory config (highest priority)\n const currentConfigPath = join(cwd, getDefaultCurrentDirConfigFilename());\n const currentConfig = loadTOMLFile(currentConfigPath);\n\n // Normalize snake_case to camelCase\n const normalizedUser = userConfig ? normalizePartialConfig(userConfig) : null;\n const normalizedEnv = envConfig ? normalizePartialConfig(envConfig) : null;\n const normalizedCurrent = currentConfig ? normalizePartialConfig(currentConfig) : null;\n\n // Merge configs (priority: current > env > user > defaults)\n const merged = mergeConfigs(\n {},\n normalizedUser,\n normalizedEnv,\n normalizedCurrent,\n options.overrides\n );\n\n // Fill missing fields with defaults\n const config = fillDefaults(merged);\n\n // Validate final config\n try {\n return configSchema.parse(config);\n } catch (error) {\n throw new Error(\n `Invalid configuration: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n"],"names":["ref","parseTOML"],"mappings":"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"}