@ncukondo/reference-manager 0.5.1 → 0.5.3

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 (55) hide show
  1. package/README.md +6 -1
  2. package/dist/chunks/{file-watcher-Dqkw6R7-.js → file-watcher-CBAbblss.js} +120 -19
  3. package/dist/chunks/file-watcher-CBAbblss.js.map +1 -0
  4. package/dist/chunks/index-Bl_mOQRe.js +1657 -0
  5. package/dist/chunks/index-Bl_mOQRe.js.map +1 -0
  6. package/dist/cli/commands/fulltext.d.ts +4 -3
  7. package/dist/cli/commands/fulltext.d.ts.map +1 -1
  8. package/dist/cli/commands/remove.d.ts +2 -1
  9. package/dist/cli/commands/remove.d.ts.map +1 -1
  10. package/dist/cli/commands/update.d.ts +2 -1
  11. package/dist/cli/commands/update.d.ts.map +1 -1
  12. package/dist/cli/index.d.ts.map +1 -1
  13. package/dist/cli/server-client.d.ts +5 -4
  14. package/dist/cli/server-client.d.ts.map +1 -1
  15. package/dist/cli.js +49 -42
  16. package/dist/cli.js.map +1 -1
  17. package/dist/core/library-interface.d.ts +22 -4
  18. package/dist/core/library-interface.d.ts.map +1 -1
  19. package/dist/core/library.d.ts +2 -10
  20. package/dist/core/library.d.ts.map +1 -1
  21. package/dist/core/reference.d.ts +1 -0
  22. package/dist/core/reference.d.ts.map +1 -1
  23. package/dist/features/duplicate/detector.d.ts.map +1 -1
  24. package/dist/features/duplicate/types.d.ts +2 -1
  25. package/dist/features/duplicate/types.d.ts.map +1 -1
  26. package/dist/features/import/cache.d.ts +8 -0
  27. package/dist/features/import/cache.d.ts.map +1 -1
  28. package/dist/features/import/detector.d.ts +11 -3
  29. package/dist/features/import/detector.d.ts.map +1 -1
  30. package/dist/features/import/fetcher.d.ts +8 -0
  31. package/dist/features/import/fetcher.d.ts.map +1 -1
  32. package/dist/features/import/importer.d.ts.map +1 -1
  33. package/dist/features/import/normalizer.d.ts +26 -0
  34. package/dist/features/import/normalizer.d.ts.map +1 -1
  35. package/dist/features/import/rate-limiter.d.ts +1 -1
  36. package/dist/features/import/rate-limiter.d.ts.map +1 -1
  37. package/dist/features/operations/cite.d.ts +3 -3
  38. package/dist/features/operations/cite.d.ts.map +1 -1
  39. package/dist/features/operations/fulltext/attach.d.ts +3 -3
  40. package/dist/features/operations/fulltext/attach.d.ts.map +1 -1
  41. package/dist/features/operations/fulltext/detach.d.ts +3 -3
  42. package/dist/features/operations/fulltext/detach.d.ts.map +1 -1
  43. package/dist/features/operations/fulltext/get.d.ts +3 -3
  44. package/dist/features/operations/fulltext/get.d.ts.map +1 -1
  45. package/dist/features/operations/remove.d.ts +3 -3
  46. package/dist/features/operations/remove.d.ts.map +1 -1
  47. package/dist/features/operations/update.d.ts +3 -3
  48. package/dist/features/operations/update.d.ts.map +1 -1
  49. package/dist/index.js +2 -2
  50. package/dist/server/routes/references.d.ts.map +1 -1
  51. package/dist/server.js +2 -2
  52. package/package.json +2 -1
  53. package/dist/chunks/file-watcher-Dqkw6R7-.js.map +0 -1
  54. package/dist/chunks/index-9dyK2f9_.js +0 -29851
  55. package/dist/chunks/index-9dyK2f9_.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Bl_mOQRe.js","sources":["../../src/features/operations/update.ts","../../src/config/csl-styles.ts","../../src/features/import/cache.ts","../../src/features/import/normalizer.ts","../../src/features/import/detector.ts","../../src/features/import/rate-limiter.ts","../../src/features/import/fetcher.ts","../../src/features/import/parser.ts","../../src/features/import/importer.ts","../../src/features/operations/add.ts","../../src/features/format/pretty.ts","../../src/features/format/bibtex.ts","../../src/features/format/citation-fallback.ts","../../src/features/format/citation-csl.ts","../../src/features/operations/cite.ts","../../src/features/operations/list.ts","../../src/features/operations/remove.ts","../../src/features/operations/search.ts","../../src/server/routes/add.ts","../../src/server/routes/cite.ts","../../src/server/routes/health.ts","../../src/server/routes/list.ts","../../src/server/routes/references.ts","../../src/server/routes/search.ts","../../src/server/index.ts"],"sourcesContent":["import type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../core/library-interface.js\";\n\n/**\n * Options for updateReference operation\n */\nexport interface UpdateOperationOptions {\n /** Reference ID or UUID */\n identifier: string;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType;\n /** Partial updates to apply to the reference */\n updates: Partial<CslItem>;\n /** How to handle ID collision: 'fail' (default) or 'suffix' */\n onIdCollision?: \"fail\" | \"suffix\";\n}\n\n/**\n * Result of updateReference operation\n */\nexport interface UpdateOperationResult {\n /** Whether the update was successful */\n updated: boolean;\n /** The updated item (if successful) */\n item?: CslItem;\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 * Update a reference in the library.\n *\n * @param library - The library to update\n * @param options - Update options including identifier, updates, and collision handling\n * @returns Result indicating success and the updated item\n */\nexport async function updateReference(\n library: ILibrary,\n options: UpdateOperationOptions\n): Promise<UpdateOperationResult> {\n const { identifier, idType = \"id\", updates, onIdCollision = \"fail\" } = options;\n\n // Update the reference using unified update() method\n const updateResult = await library.update(identifier, updates, { idType, onIdCollision });\n\n if (!updateResult.updated) {\n const result: UpdateOperationResult = { updated: false };\n if (updateResult.idCollision) {\n result.idCollision = true;\n }\n return result;\n }\n\n // Save the library\n await library.save();\n\n // Build result from UpdateResult (item is now included)\n const result: UpdateOperationResult = { updated: true };\n\n if (updateResult.item) {\n result.item = updateResult.item;\n }\n\n if (updateResult.idChanged && updateResult.newId) {\n result.idChanged = true;\n result.newId = updateResult.newId;\n }\n\n return result;\n}\n","/**\n * CSL Style Management\n *\n * Handles resolution and loading of CSL (Citation Style Language) style files.\n *\n * Style Resolution Order:\n * 1. --csl-file <path> (exact file path)\n * 2. Built-in style matching --style <name>\n * 3. Search in csl_directory paths (in array order)\n * 4. Default style from config (default_style)\n * 5. \"apa\" (hardcoded default)\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n/**\n * Built-in styles available in @citation-js/plugin-csl\n * These can be used directly without loading external files\n */\nexport const BUILTIN_STYLES = [\"apa\", \"vancouver\", \"harvard\"] as const;\n\nexport type BuiltinStyleName = (typeof BUILTIN_STYLES)[number];\n\n/**\n * Check if a style name is a built-in style\n */\nexport function isBuiltinStyle(styleName: string): styleName is BuiltinStyleName {\n return BUILTIN_STYLES.includes(styleName as BuiltinStyleName);\n}\n\nexport interface StyleResolutionOptions {\n /**\n * Exact path to CSL file (from --csl-file option)\n * Takes highest priority\n */\n cslFile?: string;\n\n /**\n * Style name to resolve (from --style option)\n */\n style?: string;\n\n /**\n * Directory or directories to search for custom CSL files\n * (from csl_directory config)\n * Can be a single string or array of strings\n */\n cslDirectory?: string | string[];\n\n /**\n * Default style to use if specified style not found\n * (from default_style config)\n */\n defaultStyle?: string;\n}\n\nexport interface StyleResolution {\n /**\n * Type of resolution: \"builtin\" for citation-js built-in styles,\n * \"custom\" for external CSL files\n */\n type: \"builtin\" | \"custom\";\n\n /**\n * The resolved style name (for built-in) or identifier (for custom)\n */\n styleName: string;\n\n /**\n * CSL XML content (only for custom styles)\n */\n styleXml?: string;\n}\n\n/**\n * Expand tilde (~) in path to home directory\n */\nfunction expandTilde(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\n return path.join(home, filePath.slice(2));\n }\n return filePath;\n}\n\n/**\n * Load CSL style file content from the given path\n *\n * @param stylePath - Path to the CSL style file\n * @returns Content of the CSL style file (XML string)\n * @throws Error if file cannot be read\n */\nexport function loadCSLStyleFile(stylePath: string): string {\n return fs.readFileSync(stylePath, \"utf-8\");\n}\n\n/**\n * Resolve the style based on resolution options\n *\n * Resolution order:\n * 1. cslFile (exact path) - throws if doesn't exist\n * 2. Built-in style matching style name\n * 3. Search in csl_directory paths (in order)\n * 4. Default style (defaultStyle) - if built-in\n * 5. \"apa\" (hardcoded fallback)\n *\n * @param options - Style resolution options\n * @returns StyleResolution with type, styleName, and optional styleXml\n * @throws Error if cslFile is specified but doesn't exist\n */\nexport function resolveStyle(options: StyleResolutionOptions): StyleResolution {\n const { cslFile, style, cslDirectory, defaultStyle } = options;\n\n // 1. If cslFile is specified, use it (highest priority)\n if (cslFile) {\n if (!fs.existsSync(cslFile)) {\n throw new Error(`CSL file '${cslFile}' not found`);\n }\n const styleXml = loadCSLStyleFile(cslFile);\n const styleName = path.basename(cslFile, \".csl\");\n return {\n type: \"custom\",\n styleName,\n styleXml,\n };\n }\n\n // Determine which style name to try\n const styleToResolve = style || defaultStyle || \"apa\";\n\n // 2. Check if it's a built-in style\n if (isBuiltinStyle(styleToResolve)) {\n return {\n type: \"builtin\",\n styleName: styleToResolve,\n };\n }\n\n // 3. Search in csl_directory paths\n if (cslDirectory) {\n const directories = Array.isArray(cslDirectory) ? cslDirectory : [cslDirectory];\n\n for (const dir of directories) {\n const expandedDir = expandTilde(dir);\n const stylePath = path.join(expandedDir, `${styleToResolve}.csl`);\n\n if (fs.existsSync(stylePath)) {\n const styleXml = loadCSLStyleFile(stylePath);\n return {\n type: \"custom\",\n styleName: styleToResolve,\n styleXml,\n };\n }\n }\n }\n\n // 4. Fall back to default style if it's built-in\n if (defaultStyle && isBuiltinStyle(defaultStyle)) {\n return {\n type: \"builtin\",\n styleName: defaultStyle,\n };\n }\n\n // 5. Fall back to apa (hardcoded default)\n return {\n type: \"builtin\",\n styleName: \"apa\",\n };\n}\n","/**\n * Response cache for PMID and DOI metadata\n *\n * In-memory cache with TTL to avoid redundant API calls.\n * - Per ADR-001: No persistent cache files on disk\n * - Cache is warm during interactive sessions (server mode)\n * - CLI invocations start fresh\n */\n\nimport type { CslItem } from \"../../core/csl-json/types.js\";\n\n/** Default TTL: 1 hour */\nconst DEFAULT_TTL_MS = 60 * 60 * 1000;\n\n/**\n * Cache configuration\n */\nexport interface CacheConfig {\n /** Time-to-live in milliseconds (default: 1 hour) */\n ttlMs?: number;\n}\n\n/**\n * Cache entry with timestamp and TTL\n */\ninterface CacheEntry {\n item: CslItem;\n cachedAt: number;\n ttlMs: number;\n}\n\n/** PMID cache: Map<pmid, CacheEntry> */\nconst pmidCache = new Map<string, CacheEntry>();\n\n/** DOI cache: Map<doi, CacheEntry> */\nconst doiCache = new Map<string, CacheEntry>();\n\n/** ISBN cache: Map<isbn, CacheEntry> */\nconst isbnCache = new Map<string, CacheEntry>();\n\n/**\n * Check if a cache entry is still valid\n */\nfunction isEntryValid(entry: CacheEntry): boolean {\n const now = Date.now();\n return now - entry.cachedAt < entry.ttlMs;\n}\n\n/**\n * Get item from cache if valid\n */\nfunction getFromCache(cache: Map<string, CacheEntry>, key: string): CslItem | undefined {\n const entry = cache.get(key);\n if (!entry) {\n return undefined;\n }\n if (!isEntryValid(entry)) {\n cache.delete(key);\n return undefined;\n }\n return entry.item;\n}\n\n/**\n * Store item in cache\n */\nfunction storeInCache(\n cache: Map<string, CacheEntry>,\n key: string,\n item: CslItem,\n config?: CacheConfig\n): void {\n const ttlMs = config?.ttlMs ?? DEFAULT_TTL_MS;\n cache.set(key, {\n item,\n cachedAt: Date.now(),\n ttlMs,\n });\n}\n\n/**\n * Get cached PMID result\n */\nexport function getPmidFromCache(pmid: string): CslItem | undefined {\n return getFromCache(pmidCache, pmid);\n}\n\n/**\n * Cache PMID result\n */\nexport function cachePmidResult(pmid: string, item: CslItem, config?: CacheConfig): void {\n storeInCache(pmidCache, pmid, item, config);\n}\n\n/**\n * Get cached DOI result\n */\nexport function getDoiFromCache(doi: string): CslItem | undefined {\n return getFromCache(doiCache, doi);\n}\n\n/**\n * Cache DOI result\n */\nexport function cacheDoiResult(doi: string, item: CslItem, config?: CacheConfig): void {\n storeInCache(doiCache, doi, item, config);\n}\n\n/**\n * Get cached ISBN result\n */\nexport function getIsbnFromCache(isbn: string): CslItem | undefined {\n return getFromCache(isbnCache, isbn);\n}\n\n/**\n * Cache ISBN result\n */\nexport function cacheIsbnResult(isbn: string, item: CslItem, config?: CacheConfig): void {\n storeInCache(isbnCache, isbn, item, config);\n}\n\n/**\n * Reset all caches (for test isolation)\n */\nexport function resetCache(): void {\n pmidCache.clear();\n doiCache.clear();\n isbnCache.clear();\n}\n","/**\n * DOI normalizer module\n *\n * Normalizes DOI identifiers by:\n * - Removing URL prefixes (doi.org, dx.doi.org)\n * - Trimming whitespace\n */\n\n/**\n * URL prefixes to remove from DOI\n */\nconst DOI_URL_PREFIXES = [\n \"https://doi.org/\",\n \"http://doi.org/\",\n \"https://dx.doi.org/\",\n \"http://dx.doi.org/\",\n];\n\n/**\n * Normalize a DOI identifier\n *\n * @param doi - DOI string, possibly with URL prefix\n * @returns Normalized DOI (10.xxx/xxx format)\n */\nexport function normalizeDoi(doi: string): string {\n // Trim whitespace\n const trimmed = doi.trim();\n\n if (!trimmed) {\n return \"\";\n }\n\n // Check for URL prefixes (case-insensitive)\n const lowerInput = trimmed.toLowerCase();\n\n for (const prefix of DOI_URL_PREFIXES) {\n if (lowerInput.startsWith(prefix.toLowerCase())) {\n // Remove the prefix while preserving the original case of the DOI\n return trimmed.slice(prefix.length);\n }\n }\n\n // No prefix found, return as-is\n return trimmed;\n}\n\n/**\n * Normalizes a PMID by removing the optional \"PMID:\" prefix and trimming whitespace.\n *\n * Supported formats:\n * - \"12345678\" -> \"12345678\"\n * - \"PMID:12345678\" -> \"12345678\"\n * - \"pmid:12345678\" -> \"12345678\"\n * - \"PMID: 12345678\" -> \"12345678\" (space after colon)\n *\n * @param pmid - The PMID string to normalize\n * @returns The normalized PMID (digits only) or empty string if invalid\n */\nexport function normalizePmid(pmid: string): string {\n // Trim whitespace\n const trimmed = pmid.trim();\n\n if (!trimmed) {\n return \"\";\n }\n\n // Remove \"PMID:\" prefix (case-insensitive, optional whitespace after colon)\n const normalized = trimmed.replace(/^pmid:\\s*/i, \"\");\n\n return normalized.trim();\n}\n\n/**\n * Normalizes an ISBN by removing the \"ISBN:\" prefix, hyphens, spaces, and uppercasing X.\n *\n * Supported formats:\n * - \"ISBN:978-4-00-000000-0\" -> \"9784000000000\"\n * - \"isbn:4-00-000000-0\" -> \"4000000000\"\n * - \"ISBN: 978 4 00 000000 0\" -> \"9784000000000\"\n * - \"ISBN:400000000x\" -> \"400000000X\" (uppercase X)\n *\n * @param isbn - The ISBN string to normalize\n * @returns The normalized ISBN (digits only, X uppercase at end for ISBN-10) or empty string if invalid\n */\nexport function normalizeIsbn(isbn: string): string {\n // Trim whitespace\n const trimmed = isbn.trim();\n\n if (!trimmed) {\n return \"\";\n }\n\n // Check for ISBN: prefix (case-insensitive)\n if (!/^isbn:/i.test(trimmed)) {\n return \"\";\n }\n\n // Remove \"ISBN:\" prefix (case-insensitive, optional whitespace after colon)\n let normalized = trimmed.replace(/^isbn:\\s*/i, \"\");\n\n // Remove hyphens and spaces\n normalized = normalized.replace(/[-\\s]/g, \"\");\n\n // Uppercase X (for ISBN-10 check digit)\n normalized = normalized.toUpperCase();\n\n return normalized;\n}\n","/**\n * Format detection module for multi-format import\n *\n * Detects input format based on:\n * - File extension (.json, .bib, .ris)\n * - Content patterns (JSON, BibTeX, RIS)\n * - Identifier patterns (PMID, DOI)\n * - Multiple whitespace-separated identifiers\n */\n\nimport { normalizeIsbn, normalizePmid } from \"./normalizer.js\";\n\n/**\n * Supported input formats\n */\nexport type InputFormat =\n | \"json\"\n | \"bibtex\"\n | \"ris\"\n | \"pmid\"\n | \"doi\"\n | \"isbn\"\n | \"identifiers\"\n | \"unknown\";\n\n/**\n * Extension to format mapping\n */\nconst EXTENSION_MAP: Record<string, InputFormat> = {\n \".json\": \"json\",\n \".bib\": \"bibtex\",\n \".ris\": \"ris\",\n};\n\n/**\n * DOI URL prefixes to strip\n */\nconst DOI_URL_PREFIXES = [\n \"https://doi.org/\",\n \"http://doi.org/\",\n \"https://dx.doi.org/\",\n \"http://dx.doi.org/\",\n];\n\n/**\n * Detect the format of the given input\n *\n * @param input - File path, identifier, or empty string for stdin\n * @param content - Optional content to analyze (for stdin or unknown extension)\n * @returns Detected format\n */\nexport function detectFormat(input: string, content?: string): InputFormat {\n // 1. Try extension-based detection first\n const extFormat = detectByExtension(input);\n if (extFormat !== \"unknown\") {\n return extFormat;\n }\n\n // 2. If content provided, try content-based detection\n if (content !== undefined) {\n const contentFormat = detectByContent(content);\n if (contentFormat !== \"unknown\") {\n return contentFormat;\n }\n }\n\n // 3. Try identifier detection on input string\n if (input.length > 0) {\n const identifierFormat = detectIdentifier(input);\n if (identifierFormat !== \"unknown\") {\n return identifierFormat;\n }\n }\n\n return \"unknown\";\n}\n\n/**\n * Detect format based on file extension\n */\nexport function detectByExtension(input: string): InputFormat {\n if (!input) return \"unknown\";\n\n // Extract extension (last dot and onwards)\n const dotIndex = input.lastIndexOf(\".\");\n if (dotIndex === -1 || dotIndex === input.length - 1) {\n return \"unknown\";\n }\n\n const ext = input.slice(dotIndex).toLowerCase();\n return EXTENSION_MAP[ext] ?? \"unknown\";\n}\n\n/**\n * Detect format based on content patterns\n */\nexport function detectByContent(content: string): InputFormat {\n const trimmed = content.trim();\n if (!trimmed) return \"unknown\";\n\n // JSON: starts with [ or {\n if (trimmed.startsWith(\"[\") || trimmed.startsWith(\"{\")) {\n return \"json\";\n }\n\n // BibTeX: starts with @\n if (trimmed.startsWith(\"@\")) {\n return \"bibtex\";\n }\n\n // RIS: starts with TY - (tag format)\n if (trimmed.startsWith(\"TY -\")) {\n return \"ris\";\n }\n\n // Check if content is multiple identifiers\n return detectIdentifier(trimmed);\n}\n\n/**\n * Detect if input is an identifier (PMID, DOI, ISBN) or multiple identifiers\n */\nfunction detectIdentifier(input: string): InputFormat {\n // Split by whitespace\n const parts = input.split(/\\s+/).filter((p) => p.length > 0);\n\n if (parts.length === 0) {\n return \"unknown\";\n }\n\n // Check each part\n const formats: (\"pmid\" | \"doi\" | \"isbn\")[] = [];\n for (const part of parts) {\n const format = detectSingleIdentifier(part);\n if (format === \"unknown\") {\n // If any part is not a valid identifier, return unknown\n return \"unknown\";\n }\n formats.push(format);\n }\n\n // Single identifier returns its specific format\n if (formats.length === 1) {\n // formats[0] is guaranteed to exist when length === 1\n return formats[0] as \"pmid\" | \"doi\" | \"isbn\";\n }\n\n // Multiple valid identifiers\n return \"identifiers\";\n}\n\n/**\n * Detect if a single string is a PMID, DOI, or ISBN\n */\nexport function detectSingleIdentifier(input: string): \"pmid\" | \"doi\" | \"isbn\" | \"unknown\" {\n // DOI: starts with 10. or is a DOI URL\n if (isDoi(input)) {\n return \"doi\";\n }\n\n // ISBN: requires ISBN: prefix\n if (isIsbn(input)) {\n return \"isbn\";\n }\n\n // PMID: numeric only (must be after ISBN check to avoid conflicts)\n if (isPmid(input)) {\n return \"pmid\";\n }\n\n return \"unknown\";\n}\n\n/**\n * Check if string is a valid DOI\n */\nexport function isDoi(input: string): boolean {\n // Check DOI URL formats\n for (const prefix of DOI_URL_PREFIXES) {\n if (input.toLowerCase().startsWith(prefix.toLowerCase())) {\n const remainder = input.slice(prefix.length);\n return isDoiFormat(remainder);\n }\n }\n\n // Check standard DOI format (10.xxx/xxx)\n return isDoiFormat(input);\n}\n\n/**\n * Check if string is a valid DOI format (10.xxx/xxx)\n */\nfunction isDoiFormat(input: string): boolean {\n // DOI starts with 10. followed by registrant code and suffix\n // Pattern: 10.{registrant}/{suffix}\n if (!input.startsWith(\"10.\")) {\n return false;\n }\n\n // Must have content after 10.\n if (input.length <= 3) {\n return false;\n }\n\n // Must have a slash after registrant code\n const slashIndex = input.indexOf(\"/\");\n if (slashIndex === -1 || slashIndex <= 3) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Check if string is a valid PMID (numeric only)\n */\nexport function isPmid(input: string): boolean {\n if (!input || input.length === 0) {\n return false;\n }\n\n // Normalize input (removes PMID: prefix if present)\n const normalized = normalizePmid(input);\n\n if (!normalized) {\n return false;\n }\n\n // PMID is all digits\n return /^\\d+$/.test(normalized);\n}\n\n/**\n * Check if string is a valid ISBN (requires ISBN: prefix)\n *\n * ISBN must have ISBN: prefix and be either:\n * - ISBN-13: 13 digits\n * - ISBN-10: 10 digits (last may be X)\n */\nexport function isIsbn(input: string): boolean {\n if (!input || input.length === 0) {\n return false;\n }\n\n // Normalize input (removes ISBN: prefix if present, hyphens, spaces)\n const normalized = normalizeIsbn(input);\n\n if (!normalized) {\n return false;\n }\n\n // Check length: ISBN-10 (10 chars) or ISBN-13 (13 chars)\n if (normalized.length !== 10 && normalized.length !== 13) {\n return false;\n }\n\n // ISBN-10: 9 digits + (digit or X)\n if (normalized.length === 10) {\n // First 9 must be digits, last can be digit or X\n if (!/^\\d{9}[\\dX]$/.test(normalized)) {\n return false;\n }\n return true;\n }\n\n // ISBN-13: all digits\n if (!/^\\d{13}$/.test(normalized)) {\n return false;\n }\n\n return true;\n}\n","/**\n * Rate limiter module for API calls\n *\n * Uses factory + lazy initialization singleton pattern:\n * - RateLimiter class: Delay-based rate limiting with configurable requests/second\n * - getRateLimiter(api, config): Returns singleton per API type\n * - resetRateLimiters(): Clears singletons for test isolation\n */\n\n/**\n * API types supported by the rate limiter\n */\nexport type ApiType = \"pubmed\" | \"crossref\" | \"isbn\";\n\n/**\n * Configuration for rate limiter\n */\nexport interface RateLimiterConfig {\n pubmedApiKey?: string;\n}\n\n/**\n * Rate limiter interface\n */\nexport interface RateLimiter {\n readonly requestsPerSecond: number;\n readonly intervalMs: number;\n readonly lastRequestTime: number;\n acquire(): Promise<void>;\n}\n\n/**\n * Rate limit settings per API type\n */\nconst RATE_LIMITS = {\n pubmed: {\n withoutApiKey: 3, // 3 req/sec\n withApiKey: 10, // 10 req/sec\n },\n crossref: 50, // 50 req/sec\n isbn: 10, // 10 req/sec (conservative for Google Books API daily limit)\n} as const;\n\n/**\n * Internal rate limiter implementation\n */\nclass RateLimiterImpl implements RateLimiter {\n readonly requestsPerSecond: number;\n readonly intervalMs: number;\n private _lastRequestTime = 0;\n private _pending: Promise<void> = Promise.resolve();\n\n constructor(requestsPerSecond: number) {\n this.requestsPerSecond = requestsPerSecond;\n this.intervalMs = 1000 / requestsPerSecond;\n }\n\n get lastRequestTime(): number {\n return this._lastRequestTime;\n }\n\n async acquire(): Promise<void> {\n // Chain onto pending promise to ensure sequential processing\n this._pending = this._pending.then(() => this._acquireInternal());\n return this._pending;\n }\n\n private async _acquireInternal(): Promise<void> {\n const now = Date.now();\n const elapsed = now - this._lastRequestTime;\n const waitTime = Math.max(0, this.intervalMs - elapsed);\n\n if (waitTime > 0 && this._lastRequestTime > 0) {\n await this._delay(waitTime);\n }\n\n this._lastRequestTime = Date.now();\n }\n\n private _delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/**\n * Singleton storage for rate limiters by API type\n */\nconst limiters = new Map<ApiType, RateLimiter>();\n\n/**\n * Create a new rate limiter instance\n */\nexport function createRateLimiter(options: {\n requestsPerSecond: number;\n}): RateLimiter {\n return new RateLimiterImpl(options.requestsPerSecond);\n}\n\n/**\n * Get singleton rate limiter for the specified API type\n *\n * Note: Configuration is only used on first call. Subsequent calls\n * return the existing singleton regardless of config changes.\n */\nexport function getRateLimiter(api: ApiType, config: RateLimiterConfig): RateLimiter {\n const existing = limiters.get(api);\n if (existing) {\n return existing;\n }\n\n const requestsPerSecond = getRequestsPerSecond(api, config);\n const limiter = createRateLimiter({ requestsPerSecond });\n limiters.set(api, limiter);\n\n return limiter;\n}\n\n/**\n * Determine requests per second based on API type and configuration\n */\nfunction getRequestsPerSecond(api: ApiType, config: RateLimiterConfig): number {\n switch (api) {\n case \"pubmed\":\n return config.pubmedApiKey ? RATE_LIMITS.pubmed.withApiKey : RATE_LIMITS.pubmed.withoutApiKey;\n case \"crossref\":\n return RATE_LIMITS.crossref;\n case \"isbn\":\n return RATE_LIMITS.isbn;\n }\n}\n\n/**\n * Reset all rate limiter singletons (for test isolation)\n */\nexport function resetRateLimiters(): void {\n limiters.clear();\n}\n","/**\n * Fetcher module for PMID and DOI metadata retrieval\n *\n * - PMID: Uses PMC Citation Exporter API (returns CSL-JSON directly)\n * - DOI: Uses citation-js plugin-doi (Cite.async)\n */\n\nimport { Cite } from \"@citation-js/core\";\nimport \"@citation-js/plugin-doi\";\nimport \"@citation-js/plugin-isbn\";\nimport { type CslItem, CslItemSchema } from \"../../core/csl-json/types.js\";\nimport { getRateLimiter } from \"./rate-limiter.js\";\n\n/** PMC Citation Exporter API base URL */\nconst PMC_API_BASE = \"https://pmc.ncbi.nlm.nih.gov/api/ctxp/v1/pubmed/\";\n\n/** Default timeout for API requests (10 seconds) */\nconst DEFAULT_TIMEOUT_MS = 10000;\n\n/** DOI pattern for validation */\nconst DOI_PATTERN = /^10\\.\\d{4,}(?:\\.\\d+)*\\/\\S+$/;\n\n/**\n * PubMed configuration for API requests\n */\nexport interface PubmedConfig {\n email?: string;\n apiKey?: string;\n}\n\n/**\n * Result of fetching a single identifier\n */\nexport type FetchResult = { success: true; item: CslItem } | { success: false; error: string };\n\n/**\n * Result of fetching a PMID (includes pmid for tracking)\n */\nexport type PmidFetchResult =\n | { pmid: string; success: true; item: CslItem }\n | { pmid: string; success: false; error: string };\n\n/**\n * Results of fetching multiple PMIDs\n */\nexport type FetchResults = PmidFetchResult[];\n\n/**\n * Build PMC API URL with query parameters\n */\nfunction buildPmcUrl(pmids: string[], config: PubmedConfig): string {\n const url = new URL(PMC_API_BASE);\n url.searchParams.set(\"format\", \"csl\");\n\n // Add each PMID as separate id parameter\n for (const pmid of pmids) {\n url.searchParams.append(\"id\", pmid);\n }\n\n if (config.email) {\n url.searchParams.set(\"email\", config.email);\n }\n if (config.apiKey) {\n url.searchParams.set(\"api_key\", config.apiKey);\n }\n\n return url.toString();\n}\n\n/**\n * Extract PMID from CSL-JSON item id field\n * PMC API returns id like \"pmid:12345678\"\n */\nfunction extractPmidFromId(id: string | undefined): string | undefined {\n if (!id) return undefined;\n const match = id.match(/^pmid:(\\d+)$/);\n return match?.[1];\n}\n\n/**\n * Fetch metadata for multiple PMIDs from PMC Citation Exporter API\n *\n * Uses batch API endpoint: /api/ctxp/v1/pubmed/?format=csl&id=1&id=2\n */\n\n/**\n * Parse raw API items and build maps of found items and validation errors\n */\nfunction parseRawItems(rawItems: unknown[]): {\n foundItems: Map<string, CslItem>;\n validationErrors: Map<string, string>;\n} {\n const foundItems = new Map<string, CslItem>();\n const validationErrors = new Map<string, string>();\n\n for (const rawItem of rawItems) {\n const parseResult = CslItemSchema.safeParse(rawItem);\n if (parseResult.success) {\n const pmid = extractPmidFromId(parseResult.data.id);\n if (pmid) {\n foundItems.set(pmid, parseResult.data);\n }\n } else {\n // Try to extract pmid even from invalid data for error reporting\n const maybeId = (rawItem as { id?: string })?.id;\n const pmid = extractPmidFromId(maybeId);\n if (pmid) {\n validationErrors.set(pmid, parseResult.error.message);\n }\n }\n }\n\n return { foundItems, validationErrors };\n}\n\n/**\n * Build fetch result for a single PMID\n */\nfunction buildPmidResult(\n pmid: string,\n foundItems: Map<string, CslItem>,\n validationErrors: Map<string, string>\n): PmidFetchResult {\n const item = foundItems.get(pmid);\n if (item) {\n return { pmid, success: true as const, item };\n }\n const validationError = validationErrors.get(pmid);\n if (validationError) {\n return {\n pmid,\n success: false as const,\n error: `Invalid CSL-JSON data: ${validationError}`,\n };\n }\n return {\n pmid,\n success: false as const,\n error: `PMID ${pmid} not found`,\n };\n}\n\nexport async function fetchPmids(pmids: string[], config: PubmedConfig): Promise<FetchResults> {\n // Return empty array for empty input\n if (pmids.length === 0) {\n return [];\n }\n\n // Apply rate limiting\n const rateLimiterConfig = config.apiKey ? { pubmedApiKey: config.apiKey } : {};\n const rateLimiter = getRateLimiter(\"pubmed\", rateLimiterConfig);\n await rateLimiter.acquire();\n\n const url = buildPmcUrl(pmids, config);\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n // Return error for all PMIDs\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n return pmids.map((pmid) => ({\n pmid,\n success: false as const,\n error: errorMsg,\n }));\n }\n\n const data = await response.json();\n\n // Normalize response to array\n const rawItems: unknown[] = Array.isArray(data) ? data : [data];\n\n // Parse raw items and build results\n const { foundItems, validationErrors } = parseRawItems(rawItems);\n\n // Build results for each requested PMID\n return pmids.map((pmid) => buildPmidResult(pmid, foundItems, validationErrors));\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return pmids.map((pmid) => ({\n pmid,\n success: false as const,\n error: errorMsg,\n }));\n }\n}\n\n/**\n * Fetch metadata for a DOI using citation-js\n *\n * Uses @citation-js/plugin-doi for content negotiation\n */\nexport async function fetchDoi(doi: string): Promise<FetchResult> {\n // Validate DOI format\n if (!DOI_PATTERN.test(doi)) {\n return {\n success: false,\n error: `Invalid DOI format: ${doi}`,\n };\n }\n\n // Apply rate limiting (crossref)\n const rateLimiter = getRateLimiter(\"crossref\", {});\n await rateLimiter.acquire();\n\n try {\n // Use citation-js Cite.async for DOI resolution\n const cite = await Cite.async(doi);\n const rawItems = cite.get({ format: \"real\", type: \"json\" });\n\n if (!rawItems || !Array.isArray(rawItems) || rawItems.length === 0) {\n return {\n success: false,\n error: `No data returned for DOI ${doi}`,\n };\n }\n\n // Validate using zod schema\n const parseResult = CslItemSchema.safeParse(rawItems[0]);\n if (!parseResult.success) {\n return {\n success: false,\n error: `Invalid CSL-JSON data for DOI ${doi}: ${parseResult.error.message}`,\n };\n }\n\n return { success: true, item: parseResult.data };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMsg,\n };\n }\n}\n\n/** ISBN-10 pattern: 9 digits + (digit or X) */\nconst ISBN10_PATTERN = /^\\d{9}[\\dX]$/;\n\n/** ISBN-13 pattern: 13 digits */\nconst ISBN13_PATTERN = /^\\d{13}$/;\n\n/**\n * Fetch metadata for an ISBN using Google Books API via citation-js\n *\n * @param isbn - Normalized ISBN (10 or 13 digits, no hyphens)\n * @returns FetchResult with CSL-JSON item or error\n */\nexport async function fetchIsbn(isbn: string): Promise<FetchResult> {\n // Validate ISBN format\n if (!ISBN10_PATTERN.test(isbn) && !ISBN13_PATTERN.test(isbn)) {\n return {\n success: false,\n error: `Invalid ISBN format: ${isbn}`,\n };\n }\n\n // Apply rate limiting (google books - daily limit so we use a generic limiter)\n const rateLimiter = getRateLimiter(\"isbn\", {});\n await rateLimiter.acquire();\n\n try {\n // Use citation-js Cite.async for ISBN resolution\n const cite = await Cite.async(isbn);\n const rawItems = cite.get({ format: \"real\", type: \"json\" });\n\n if (!rawItems || !Array.isArray(rawItems) || rawItems.length === 0) {\n return {\n success: false,\n error: `No data returned for ISBN ${isbn}`,\n };\n }\n\n // Validate using zod schema\n const parseResult = CslItemSchema.safeParse(rawItems[0]);\n if (!parseResult.success) {\n return {\n success: false,\n error: `Invalid CSL-JSON data for ISBN ${isbn}: ${parseResult.error.message}`,\n };\n }\n\n return { success: true, item: parseResult.data };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMsg,\n };\n }\n}\n","/**\n * Parser module for BibTeX and RIS formats\n *\n * Uses citation-js plugins for parsing:\n * - @citation-js/plugin-bibtex for BibTeX\n * - @citation-js/plugin-ris for RIS\n */\n\nimport { Cite } from \"@citation-js/core\";\nimport \"@citation-js/plugin-bibtex\";\nimport \"@citation-js/plugin-ris\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\n\n/**\n * Result of a parse operation\n */\nexport type ParseResult = {\n success: boolean;\n items: CslItem[];\n error?: string;\n};\n\n/**\n * Parse BibTeX content to CSL-JSON\n *\n * @param content - BibTeX content string\n * @returns Parse result with CSL-JSON items\n */\nexport function parseBibtex(content: string): ParseResult {\n return parseWithCitationJs(content, \"bibtex\");\n}\n\n/**\n * Parse RIS content to CSL-JSON\n *\n * @param content - RIS content string\n * @returns Parse result with CSL-JSON items\n */\nexport function parseRis(content: string): ParseResult {\n return parseWithCitationJs(content, \"ris\");\n}\n\n/**\n * Parse content using citation-js\n */\nfunction parseWithCitationJs(content: string, format: string): ParseResult {\n const trimmed = content.trim();\n\n // Handle empty input\n if (!trimmed) {\n return { success: true, items: [] };\n }\n\n try {\n // Parse with citation-js (auto-detection works well for bibtex/ris)\n const cite = new Cite(trimmed);\n\n // Get CSL-JSON output\n const items = cite.get({ format: \"real\", type: \"json\" }) as CslItem[];\n\n // Handle case where parsing produces no results\n if (!items || items.length === 0) {\n // Check if input looks like valid format but has no entries\n if (isEmptyFormat(trimmed, format)) {\n return { success: true, items: [] };\n }\n\n return {\n success: false,\n items: [],\n error: `No valid ${format.toUpperCase()} entries found`,\n };\n }\n\n return { success: true, items };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Check if this is truly empty content (comments only for bibtex)\n if (isEmptyFormat(trimmed, format)) {\n return { success: true, items: [] };\n }\n\n return {\n success: false,\n items: [],\n error: `Failed to parse ${format.toUpperCase()}: ${errorMessage}`,\n };\n }\n}\n\n/**\n * Check if content is \"empty\" for the given format\n * (e.g., only comments for BibTeX)\n */\nfunction isEmptyFormat(content: string, format: string): boolean {\n if (format === \"bibtex\") {\n // BibTeX comments start with %\n const lines = content.split(\"\\n\");\n return lines.every((line) => {\n const trimmed = line.trim();\n return trimmed === \"\" || trimmed.startsWith(\"%\");\n });\n }\n\n return false;\n}\n","/**\n * Importer orchestration module\n *\n * Coordinates format detection, parsing, and fetching to import references\n * from various input formats.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport { CslItemSchema } from \"../../core/csl-json/types.js\";\nimport {\n cacheDoiResult,\n cacheIsbnResult,\n cachePmidResult,\n getDoiFromCache,\n getIsbnFromCache,\n getPmidFromCache,\n} from \"./cache.js\";\nimport { detectByContent, detectByExtension, isDoi, isIsbn, isPmid } from \"./detector.js\";\nimport type { InputFormat } from \"./detector.js\";\nimport { fetchDoi, fetchIsbn, fetchPmids } from \"./fetcher.js\";\nimport type { PubmedConfig } from \"./fetcher.js\";\nimport { normalizeDoi, normalizeIsbn, normalizePmid } from \"./normalizer.js\";\nimport { parseBibtex, parseRis } from \"./parser.js\";\n\n/**\n * Result of importing a single item\n */\nexport type ImportItemResult =\n | { success: true; item: CslItem; source: string }\n | { success: false; error: string; source: string };\n\n/**\n * Result of an import operation\n */\nexport interface ImportResult {\n results: ImportItemResult[];\n}\n\n/**\n * Options for import operations\n */\nexport interface ImportOptions {\n pubmedConfig?: PubmedConfig;\n}\n\n/**\n * Classified identifiers\n */\ninterface ClassifiedIdentifiers {\n pmids: string[];\n dois: string[];\n isbns: string[];\n unknowns: string[];\n}\n\n/**\n * Classify identifiers into PMIDs, DOIs, and unknowns\n */\nfunction classifyIdentifiers(identifiers: string[]): ClassifiedIdentifiers {\n const pmids: string[] = [];\n const dois: string[] = [];\n const isbns: string[] = [];\n const unknowns: string[] = [];\n\n for (const id of identifiers) {\n if (isPmid(id)) {\n pmids.push(normalizePmid(id));\n } else if (isDoi(id)) {\n dois.push(normalizeDoi(id));\n } else if (isIsbn(id)) {\n isbns.push(normalizeIsbn(id));\n } else {\n unknowns.push(id);\n }\n }\n\n return { pmids, dois, isbns, unknowns };\n}\n\n/**\n * Build error results for unknown identifiers\n */\nfunction buildUnknownResults(unknowns: string[]): ImportItemResult[] {\n return unknowns.map((unknown) => ({\n success: false as const,\n error: `Cannot interpret '${unknown}' as identifier (not a valid PMID or DOI)`,\n source: unknown,\n }));\n}\n\n/**\n * Fetch PMIDs with cache support\n */\nasync function fetchPmidsWithCache(\n pmids: string[],\n pubmedConfig: PubmedConfig\n): Promise<ImportItemResult[]> {\n const results: ImportItemResult[] = [];\n const pmidsToFetch: string[] = [];\n\n // Check cache first\n for (const pmid of pmids) {\n const cached = getPmidFromCache(pmid);\n if (cached) {\n results.push({ success: true, item: cached, source: pmid });\n } else {\n pmidsToFetch.push(pmid);\n }\n }\n\n // Fetch uncached PMIDs\n if (pmidsToFetch.length > 0) {\n const fetchResults = await fetchPmids(pmidsToFetch, pubmedConfig);\n for (const fetchResult of fetchResults) {\n if (fetchResult.success) {\n cachePmidResult(fetchResult.pmid, fetchResult.item);\n results.push({\n success: true,\n item: fetchResult.item,\n source: fetchResult.pmid,\n });\n } else {\n results.push({\n success: false,\n error: fetchResult.error,\n source: fetchResult.pmid,\n });\n }\n }\n }\n\n return results;\n}\n\n/**\n * Fetch DOIs with cache support\n */\nasync function fetchDoisWithCache(dois: string[]): Promise<ImportItemResult[]> {\n const results: ImportItemResult[] = [];\n\n for (const doi of dois) {\n const cached = getDoiFromCache(doi);\n if (cached) {\n results.push({ success: true, item: cached, source: doi });\n continue;\n }\n\n const fetchResult = await fetchDoi(doi);\n if (fetchResult.success) {\n cacheDoiResult(doi, fetchResult.item);\n results.push({ success: true, item: fetchResult.item, source: doi });\n } else {\n results.push({ success: false, error: fetchResult.error, source: doi });\n }\n }\n\n return results;\n}\n\n/**\n * Fetch ISBNs with caching\n */\nasync function fetchIsbnsWithCache(isbns: string[]): Promise<ImportItemResult[]> {\n const results: ImportItemResult[] = [];\n\n for (const isbn of isbns) {\n const cached = getIsbnFromCache(isbn);\n if (cached) {\n results.push({ success: true, item: cached, source: isbn });\n continue;\n }\n\n const fetchResult = await fetchIsbn(isbn);\n if (fetchResult.success) {\n cacheIsbnResult(isbn, fetchResult.item);\n results.push({ success: true, item: fetchResult.item, source: isbn });\n } else {\n results.push({ success: false, error: fetchResult.error, source: isbn });\n }\n }\n\n return results;\n}\n\n/**\n * Parse JSON content and return import result\n */\nfunction parseJsonContent(content: string): ImportResult {\n try {\n const parsed = JSON.parse(content);\n const items: unknown[] = Array.isArray(parsed) ? parsed : [parsed];\n\n if (items.length === 0) {\n return { results: [] };\n }\n\n const results: ImportItemResult[] = [];\n for (const item of items) {\n const parseResult = CslItemSchema.safeParse(item);\n if (parseResult.success) {\n results.push({ success: true, item: parseResult.data, source: \"json\" });\n } else {\n results.push({\n success: false,\n error: `Invalid CSL-JSON: ${parseResult.error.message}`,\n source: \"json\",\n });\n }\n }\n return { results };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n results: [{ success: false, error: `Failed to parse JSON: ${message}`, source: \"json\" }],\n };\n }\n}\n\n/**\n * Parse BibTeX content and return import result\n */\nfunction parseBibtexContent(content: string): ImportResult {\n const parseResult = parseBibtex(content);\n\n if (!parseResult.success) {\n return {\n results: [\n { success: false, error: parseResult.error ?? \"Failed to parse BibTeX\", source: \"bibtex\" },\n ],\n };\n }\n\n if (parseResult.items.length === 0) {\n return { results: [] };\n }\n\n return {\n results: parseResult.items.map((item) => ({\n success: true as const,\n item,\n source: \"bibtex\",\n })),\n };\n}\n\n/**\n * Parse RIS content and return import result\n */\nfunction parseRisContent(content: string): ImportResult {\n const parseResult = parseRis(content);\n\n if (!parseResult.success) {\n return {\n results: [\n { success: false, error: parseResult.error ?? \"Failed to parse RIS\", source: \"ris\" },\n ],\n };\n }\n\n if (parseResult.items.length === 0) {\n return { results: [] };\n }\n\n return {\n results: parseResult.items.map((item) => ({\n success: true as const,\n item,\n source: \"ris\",\n })),\n };\n}\n\n/**\n * Import references from content string\n *\n * @param content - The content to parse\n * @param format - The format of the content (or \"auto\" for detection)\n * @param options - Import options\n * @returns Import result with parsed items\n */\nexport async function importFromContent(\n content: string,\n format: InputFormat | \"auto\",\n _options: ImportOptions\n): Promise<ImportResult> {\n // Determine the actual format\n let actualFormat: InputFormat;\n if (format === \"auto\") {\n actualFormat = detectByContent(content);\n if (actualFormat === \"unknown\") {\n return {\n results: [\n {\n success: false,\n error: \"Cannot detect input format. Use --format to specify explicitly.\",\n source: \"content\",\n },\n ],\n };\n }\n } else {\n actualFormat = format;\n }\n\n // Parse based on format\n switch (actualFormat) {\n case \"json\":\n return parseJsonContent(content);\n case \"bibtex\":\n return parseBibtexContent(content);\n case \"ris\":\n return parseRisContent(content);\n default:\n return {\n results: [\n {\n success: false,\n error: `Unsupported format for content parsing: ${actualFormat}`,\n source: \"content\",\n },\n ],\n };\n }\n}\n\n/**\n * Import references from identifier strings (PMID or DOI)\n *\n * @param identifiers - Array of identifier strings\n * @param options - Import options (requires pubmedConfig for PMID fetching)\n * @returns Import result with fetched items\n */\nexport async function importFromIdentifiers(\n identifiers: string[],\n options: ImportOptions\n): Promise<ImportResult> {\n if (identifiers.length === 0) {\n return { results: [] };\n }\n\n // Classify identifiers\n const { pmids, dois, isbns, unknowns } = classifyIdentifiers(identifiers);\n\n // Collect results\n const results: ImportItemResult[] = [];\n\n // Add errors for unknown identifiers\n results.push(...buildUnknownResults(unknowns));\n\n // Fetch PMIDs with cache\n const pmidResults = await fetchPmidsWithCache(pmids, options.pubmedConfig ?? {});\n results.push(...pmidResults);\n\n // Fetch DOIs with cache\n const doiResults = await fetchDoisWithCache(dois);\n results.push(...doiResults);\n\n // Fetch ISBNs with cache\n const isbnResults = await fetchIsbnsWithCache(isbns);\n results.push(...isbnResults);\n\n return { results };\n}\n\n/**\n * Options for importFromInputs\n */\nexport interface ImportInputsOptions extends ImportOptions {\n /** Explicit format specification (default: auto) */\n format?: InputFormat | \"auto\";\n /** Content from stdin (if provided, processed before file/identifier inputs) */\n stdinContent?: string;\n}\n\n/**\n * Unified entry point for importing references from file paths or identifiers\n *\n * Classifies inputs as files or identifiers:\n * - If path exists as file → read and parse\n * - If path does not exist → interpret as identifier (PMID/DOI)\n *\n * @param inputs - Array of file paths or identifier strings\n * @param options - Import options including format specification\n * @returns Import result with all parsed/fetched items\n */\n\n/**\n * Check if input looks like a file path (has file-like extension)\n */\nfunction looksLikeFilePath(input: string): boolean {\n const fileExtensions = [\".json\", \".bib\", \".ris\", \".txt\", \".xml\", \".yaml\", \".yml\"];\n const lowerInput = input.toLowerCase();\n return fileExtensions.some((ext) => lowerInput.endsWith(ext));\n}\n\n/**\n * Process a single file input\n */\nasync function processFile(\n filePath: string,\n options: ImportInputsOptions\n): Promise<ImportItemResult[]> {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n\n // Determine format\n let format: InputFormat | \"auto\";\n if (options.format && options.format !== \"auto\") {\n format = options.format;\n } else {\n // Try extension first\n const extFormat = detectByExtension(filePath);\n format = extFormat !== \"unknown\" ? extFormat : \"auto\";\n }\n\n const result = await importFromContent(content, format, options);\n\n // Update source to be the file path\n return result.results.map((r) => ({\n ...r,\n source: filePath,\n }));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return [\n {\n success: false,\n error: `Failed to read file: ${message}`,\n source: filePath,\n },\n ];\n }\n}\n\n/**\n * Process identifier inputs (PMID/DOI)\n */\nasync function processIdentifiers(\n inputs: string[],\n options: ImportInputsOptions\n): Promise<ImportItemResult[]> {\n const results: ImportItemResult[] = [];\n const validIdentifiers: string[] = [];\n\n // Separate valid identifiers from invalid inputs\n for (const input of inputs) {\n // Check if it's a valid identifier\n const isValidPmid = isPmid(input);\n const isValidDoi = isDoi(input);\n\n if (isValidPmid || isValidDoi) {\n validIdentifiers.push(input);\n } else {\n // Not a valid identifier\n const hint = looksLikeFilePath(input)\n ? \" Hint: If this is a file path, check that the file exists.\"\n : \"\";\n results.push({\n success: false,\n error: `Cannot interpret '${input}' as identifier (not a valid PMID or DOI).${hint}`,\n source: input,\n });\n }\n }\n\n // Fetch valid identifiers\n if (validIdentifiers.length > 0) {\n const fetchResult = await importFromIdentifiers(validIdentifiers, options);\n results.push(...fetchResult.results);\n }\n\n return results;\n}\n\nexport async function importFromInputs(\n inputs: string[],\n options: ImportInputsOptions\n): Promise<ImportResult> {\n const allResults: ImportItemResult[] = [];\n\n // Process stdinContent if provided\n if (options.stdinContent?.trim()) {\n const stdinResults = await processStdinContent(options.stdinContent, options);\n allResults.push(...stdinResults);\n }\n\n // Process file/identifier inputs\n if (inputs.length > 0) {\n const identifiersToFetch: string[] = [];\n\n // Process each input\n for (const input of inputs) {\n if (existsSync(input)) {\n // Input is an existing file\n const fileResults = await processFile(input, options);\n allResults.push(...fileResults);\n } else {\n // Input does not exist as file - treat as potential identifier\n identifiersToFetch.push(input);\n }\n }\n\n // Process identifiers\n if (identifiersToFetch.length > 0) {\n const identifierResults = await processIdentifiers(identifiersToFetch, options);\n allResults.push(...identifierResults);\n }\n }\n\n return { results: allResults };\n}\n\n/**\n * Process stdin content based on format detection\n * - For file formats (json/bibtex/ris): parse directly\n * - For identifier formats (pmid/doi) or auto with identifiers: split and process\n */\nasync function processStdinContent(\n content: string,\n options: ImportInputsOptions\n): Promise<ImportItemResult[]> {\n const format = options.format || \"auto\";\n\n // If explicit file format specified, parse as content\n if (format === \"json\" || format === \"bibtex\" || format === \"ris\") {\n const result = await importFromContent(content, format, options);\n return result.results.map((r) => ({\n ...r,\n source: r.source === \"content\" ? \"stdin\" : r.source,\n }));\n }\n\n // If explicit identifier format, split and process\n if (format === \"pmid\" || format === \"doi\") {\n const identifiers = content.split(/\\s+/).filter((s) => s.length > 0);\n return processIdentifiers(identifiers, options);\n }\n\n // Auto-detect format from content\n const detectedFormat = detectByContent(content);\n\n if (detectedFormat === \"json\" || detectedFormat === \"bibtex\" || detectedFormat === \"ris\") {\n // File format detected - parse as content\n const result = await importFromContent(content, detectedFormat, options);\n return result.results.map((r) => ({\n ...r,\n source: r.source === \"content\" ? \"stdin\" : r.source,\n }));\n }\n\n // Not a file format - treat as whitespace-separated identifiers\n const identifiers = content.split(/\\s+/).filter((s) => s.length > 0);\n if (identifiers.length === 0) {\n return [];\n }\n\n return processIdentifiers(identifiers, options);\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary } from \"../../core/library-interface.js\";\nimport { detectDuplicate } from \"../duplicate/detector.js\";\nimport type { InputFormat } from \"../import/detector.js\";\nimport type { PubmedConfig } from \"../import/fetcher.js\";\nimport {\n type ImportInputsOptions,\n type ImportItemResult,\n importFromInputs,\n} from \"../import/importer.js\";\n\n/**\n * Options for adding references\n */\nexport interface AddReferencesOptions {\n /** Skip duplicate detection */\n force?: boolean;\n /** Explicit input format (default: auto) */\n format?: InputFormat | \"auto\";\n /** PubMed API configuration */\n pubmedConfig?: PubmedConfig;\n /** Content from stdin (if provided, processed before file/identifier inputs) */\n stdinContent?: string;\n}\n\n/**\n * Information about a successfully added reference\n */\nexport interface AddedItem {\n id: string;\n title: string;\n /** True if the ID was changed due to collision */\n idChanged?: boolean;\n /** Original ID before collision resolution */\n originalId?: string;\n}\n\n/**\n * Information about a failed import\n */\nexport interface FailedItem {\n source: string;\n error: string;\n}\n\n/**\n * Information about a skipped duplicate\n */\nexport interface SkippedItem {\n source: string;\n existingId: string;\n}\n\n/**\n * Result of addReferences operation\n */\nexport interface AddReferencesResult {\n added: AddedItem[];\n failed: FailedItem[];\n skipped: SkippedItem[];\n}\n\n/**\n * Add references to a library from various input sources.\n *\n * This function orchestrates:\n * 1. Import from inputs (files or identifiers)\n * 2. Duplicate detection (unless force=true)\n * 3. ID collision resolution\n * 4. Library save\n *\n * @param inputs - File paths or identifiers (PMID, DOI)\n * @param library - Target library\n * @param options - Add options\n * @returns Result with added, failed, and skipped items\n */\nexport async function addReferences(\n inputs: string[],\n library: ILibrary,\n options: AddReferencesOptions\n): Promise<AddReferencesResult> {\n const added: AddedItem[] = [];\n const failed: FailedItem[] = [];\n const skipped: SkippedItem[] = [];\n\n // 1. Import from inputs\n const importOptions = buildImportOptions(options);\n const importResult = await importFromInputs(inputs, importOptions);\n\n // Get existing items for duplicate/collision checks (getAll now returns CslItem[] directly)\n const existingItems = await library.getAll();\n\n // Track IDs we've added in this batch (for collision detection within batch)\n const addedIds = new Set<string>();\n\n // 2. Process each import result\n for (const result of importResult.results) {\n const processed = await processImportResult(\n result,\n existingItems,\n addedIds,\n options.force ?? false,\n library\n );\n\n if (processed.type === \"failed\") {\n failed.push(processed.item);\n } else if (processed.type === \"skipped\") {\n skipped.push(processed.item);\n } else {\n added.push(processed.item);\n }\n }\n\n // 3. Save library if any items were added\n if (added.length > 0) {\n await library.save();\n }\n\n return { added, failed, skipped };\n}\n\n/**\n * Build import options from add options\n */\nfunction buildImportOptions(options: AddReferencesOptions): ImportInputsOptions {\n const importOptions: ImportInputsOptions = {};\n if (options.format !== undefined) {\n importOptions.format = options.format;\n }\n if (options.pubmedConfig !== undefined) {\n importOptions.pubmedConfig = options.pubmedConfig;\n }\n if (options.stdinContent !== undefined) {\n importOptions.stdinContent = options.stdinContent;\n }\n return importOptions;\n}\n\ntype ProcessResult =\n | { type: \"added\"; item: AddedItem }\n | { type: \"failed\"; item: FailedItem }\n | { type: \"skipped\"; item: SkippedItem };\n\n/**\n * Process a single import result\n */\nasync function processImportResult(\n result: ImportItemResult,\n existingItems: CslItem[],\n addedIds: Set<string>,\n force: boolean,\n library: ILibrary\n): Promise<ProcessResult> {\n if (!result.success) {\n return { type: \"failed\", item: { source: result.source, error: result.error } };\n }\n\n const item = result.item;\n\n // Check for duplicates (unless force=true)\n if (!force) {\n const duplicateResult = detectDuplicate(item, existingItems);\n const existingMatch = duplicateResult.matches[0];\n if (existingMatch) {\n return {\n type: \"skipped\",\n item: { source: result.source, existingId: existingMatch.existing.id ?? \"\" },\n };\n }\n }\n\n // Resolve ID collision\n const allExistingIds = new Set([...existingItems.map((i) => i.id), ...addedIds]);\n const { id, changed } = resolveIdCollision(item.id, allExistingIds);\n\n const finalItem: CslItem = { ...item, id };\n\n // Add to library\n await library.add(finalItem);\n addedIds.add(id);\n\n // Build result\n const addedItem: AddedItem = {\n id,\n title: typeof finalItem.title === \"string\" ? finalItem.title : \"\",\n };\n\n if (changed) {\n addedItem.idChanged = true;\n addedItem.originalId = item.id;\n }\n\n return { type: \"added\", item: addedItem };\n}\n\n/**\n * Generate an alphabetic suffix for ID collision resolution.\n * 0 -> 'a', 1 -> 'b', ..., 25 -> 'z', 26 -> 'aa', etc.\n */\nfunction 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 */\nfunction resolveIdCollision(\n baseId: string,\n existingIds: Set<string>\n): { id: string; changed: boolean } {\n if (!existingIds.has(baseId)) {\n return { id: baseId, changed: false };\n }\n\n // Find next available suffix\n let index = 0;\n let newId: string;\n\n do {\n const suffix = generateSuffix(index);\n newId = `${baseId}${suffix}`;\n index++;\n } while (existingIds.has(newId));\n\n return { id: newId, changed: true };\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\n\n/**\n * Format a single author as \"Family, Given-Initial.\"\n */\nfunction formatAuthor(author: {\n family?: string | undefined;\n given?: string | undefined;\n}): string {\n const family = author.family || \"\";\n const givenInitial = author.given ? `${author.given.charAt(0)}.` : \"\";\n return givenInitial ? `${family}, ${givenInitial}` : family;\n}\n\n/**\n * Format authors array as \"Family1, G.; Family2, G.\"\n */\nfunction formatAuthors(\n authors: Array<{\n family?: string | undefined;\n given?: string | undefined;\n literal?: string | undefined;\n \"dropping-particle\"?: string | undefined;\n \"non-dropping-particle\"?: string | undefined;\n suffix?: string | undefined;\n }>\n): string {\n return authors.map(formatAuthor).join(\"; \");\n}\n\n/**\n * Format a single reference in pretty format\n */\nfunction formatSingleReference(item: CslItem): string {\n const lines: string[] = [];\n\n // Header line: [id] title\n const header = item.title ? `[${item.id}] ${item.title}` : `[${item.id}]`;\n lines.push(header);\n\n // Authors (if present)\n if (item.author && item.author.length > 0) {\n lines.push(` Authors: ${formatAuthors(item.author)}`);\n }\n\n // Year\n const year = item.issued?.[\"date-parts\"]?.[0]?.[0];\n lines.push(` Year: ${year || \"(no year)\"}`);\n\n // Type\n lines.push(` Type: ${item.type}`);\n\n // DOI (if present)\n if (item.DOI) {\n lines.push(` DOI: ${item.DOI}`);\n }\n\n // PMID (if present)\n if (item.PMID) {\n lines.push(` PMID: ${item.PMID}`);\n }\n\n // PMCID (if present)\n if (item.PMCID) {\n lines.push(` PMCID: ${item.PMCID}`);\n }\n\n // URL (if present)\n if (item.URL) {\n lines.push(` URL: ${item.URL}`);\n }\n\n // UUID (always)\n const uuid = item.custom?.uuid || \"(no uuid)\";\n lines.push(` UUID: ${uuid}`);\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format references in pretty-printed format\n */\nexport function formatPretty(items: CslItem[]): string {\n if (items.length === 0) {\n return \"\";\n }\n\n return items.map(formatSingleReference).join(\"\\n\\n\");\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\n\n/**\n * Map CSL-JSON type to BibTeX entry type\n */\nfunction mapEntryType(cslType: string): string {\n const typeMap: Record<string, string> = {\n article: \"article\",\n \"article-journal\": \"article\",\n \"article-magazine\": \"article\",\n \"article-newspaper\": \"article\",\n book: \"book\",\n chapter: \"inbook\",\n \"paper-conference\": \"inproceedings\",\n thesis: \"phdthesis\",\n report: \"techreport\",\n webpage: \"misc\",\n };\n\n return typeMap[cslType] || \"misc\";\n}\n\n/**\n * Format a single author as \"Family, Given\"\n */\nfunction formatBibtexAuthor(author: {\n family?: string | undefined;\n given?: string | undefined;\n literal?: string | undefined;\n}): string {\n if (author.literal) {\n return author.literal;\n }\n const family = author.family || \"\";\n const given = author.given || \"\";\n return given ? `${family}, ${given}` : family;\n}\n\n/**\n * Format authors for BibTeX as \"Family1, Given1 and Family2, Given2\"\n */\nfunction formatBibtexAuthors(\n authors: Array<{\n family?: string | undefined;\n given?: string | undefined;\n literal?: string | undefined;\n \"dropping-particle\"?: string | undefined;\n \"non-dropping-particle\"?: string | undefined;\n suffix?: string | undefined;\n }>\n): string {\n return authors.map(formatBibtexAuthor).join(\" and \");\n}\n\n/**\n * Format a BibTeX field\n */\nfunction formatField(name: string, value: string): string {\n return ` ${name} = {${value}},`;\n}\n\n/**\n * Add basic bibliographic fields to BibTeX entry\n */\nfunction addBasicFields(lines: string[], item: CslItem): void {\n // Title\n if (item.title) {\n lines.push(formatField(\"title\", item.title));\n }\n\n // Authors\n if (item.author && item.author.length > 0) {\n lines.push(formatField(\"author\", formatBibtexAuthors(item.author)));\n }\n\n // Year\n const year = item.issued?.[\"date-parts\"]?.[0]?.[0];\n if (year) {\n lines.push(formatField(\"year\", String(year)));\n }\n}\n\n/**\n * Add publication details to BibTeX entry\n */\nfunction addPublicationDetails(lines: string[], item: CslItem, entryType: string): void {\n // Container-title (journal or booktitle depending on type)\n if (item[\"container-title\"]) {\n if (entryType === \"article\") {\n lines.push(formatField(\"journal\", item[\"container-title\"]));\n } else if (entryType === \"inbook\" || entryType === \"inproceedings\") {\n lines.push(formatField(\"booktitle\", item[\"container-title\"]));\n }\n }\n\n // Volume\n if (item.volume) {\n lines.push(formatField(\"volume\", item.volume));\n }\n\n // Issue -> number\n if (item.issue) {\n lines.push(formatField(\"number\", item.issue));\n }\n\n // Pages\n if (item.page) {\n lines.push(formatField(\"pages\", item.page));\n }\n\n // Publisher\n if (item.publisher) {\n lines.push(formatField(\"publisher\", item.publisher));\n }\n}\n\n/**\n * Add identifier fields to BibTeX entry\n */\nfunction addIdentifierFields(lines: string[], item: CslItem): void {\n // DOI\n if (item.DOI) {\n lines.push(formatField(\"doi\", item.DOI));\n }\n\n // URL\n if (item.URL) {\n lines.push(formatField(\"url\", item.URL));\n }\n\n // PMID or PMCID in note field\n if (item.PMID) {\n lines.push(formatField(\"note\", `PMID: ${item.PMID}`));\n } else if (item.PMCID) {\n lines.push(formatField(\"note\", `PMCID: ${item.PMCID}`));\n }\n}\n\n/**\n * Format a single reference as BibTeX entry\n */\nfunction formatSingleBibtexEntry(item: CslItem): string {\n const entryType = mapEntryType(item.type);\n const lines: string[] = [];\n\n // Opening line: @type{citation-key,\n lines.push(`@${entryType}{${item.id},`);\n\n // Add fields in sections\n addBasicFields(lines, item);\n addPublicationDetails(lines, item, entryType);\n addIdentifierFields(lines, item);\n\n // Closing brace\n lines.push(\"}\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format references as BibTeX\n */\nexport function formatBibtex(items: CslItem[]): string {\n if (items.length === 0) {\n return \"\";\n }\n\n return items.map(formatSingleBibtexEntry).join(\"\\n\\n\");\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\n\n/**\n * Extract first author name with initial\n * Returns \"Family G\" or \"Family\" if no given name\n */\nfunction formatFirstAuthor(item: CslItem): string {\n if (!item.author || item.author.length === 0) {\n return \"Unknown\";\n }\n\n const firstAuthor = item.author[0];\n if (!firstAuthor) {\n return \"Unknown\";\n }\n\n const family = firstAuthor.family || \"Unknown\";\n const givenInitial = firstAuthor.given ? firstAuthor.given[0] : \"\";\n\n if (givenInitial) {\n return `${family} ${givenInitial}`;\n }\n return family;\n}\n\n/**\n * Check if item has multiple authors\n */\nfunction hasMultipleAuthors(item: CslItem): boolean {\n return (item.author?.length || 0) > 1;\n}\n\n/**\n * Extract year from CSL-JSON issued field\n */\nfunction extractYear(item: CslItem): string {\n if (item.issued?.[\"date-parts\"]?.[0]?.[0]) {\n return String(item.issued[\"date-parts\"][0][0]);\n }\n return \"n.d.\";\n}\n\n/**\n * Get journal abbreviation (prefer short title)\n */\nfunction getJournalAbbrev(item: CslItem): string {\n const containerTitleShort = (item as Record<string, unknown>)[\"container-title-short\"];\n if (typeof containerTitleShort === \"string\") {\n return containerTitleShort;\n }\n return item[\"container-title\"] || \"\";\n}\n\n/**\n * Format volume/issue/pages section\n * Returns formats like: \"10(2):123-145\", \"10:123-145\", \"10(2)\", \"10\", or \"\"\n */\nfunction formatVolumeIssuePage(item: CslItem): string {\n const volume = item.volume;\n const issue = item.issue;\n const page = item.page;\n\n if (!volume && !issue && !page) {\n return \"\";\n }\n\n let result = \"\";\n\n if (volume) {\n result += volume;\n if (issue) {\n result += `(${issue})`;\n }\n if (page) {\n result += `:${page}`;\n }\n } else if (page) {\n result += page;\n }\n\n return result;\n}\n\n/**\n * Get identifier (PMID > DOI > URL priority)\n */\nfunction getIdentifier(item: CslItem): string {\n if (item.PMID) {\n return `PMID:${item.PMID}`;\n }\n if (item.DOI) {\n return `DOI:${item.DOI}`;\n }\n if (item.URL) {\n return item.URL;\n }\n return \"\";\n}\n\n/**\n * Format a single bibliography entry\n */\nfunction formatBibliographyEntry(item: CslItem): string {\n const parts: string[] = [];\n\n // Author\n const author = formatFirstAuthor(item);\n const etAl = hasMultipleAuthors(item) ? \" et al\" : \"\";\n parts.push(`${author}${etAl}.`);\n\n // Journal\n const journal = getJournalAbbrev(item);\n if (journal) {\n parts.push(`${journal}.`);\n }\n\n // Year and volume/issue/pages\n const year = extractYear(item);\n const volumeIssuePage = formatVolumeIssuePage(item);\n\n if (volumeIssuePage) {\n parts.push(`${year};${volumeIssuePage}.`);\n } else {\n parts.push(`${year}.`);\n }\n\n // Identifier\n const identifier = getIdentifier(item);\n if (identifier) {\n parts.push(`${identifier}.`);\n }\n\n // Title\n if (item.title) {\n parts.push(`${item.title}.`);\n }\n\n return parts.join(\" \");\n}\n\n/**\n * Get first author family name only (for in-text citations)\n */\nfunction getFirstAuthorFamilyName(item: CslItem): string {\n if (!item.author || item.author.length === 0) {\n return \"Unknown\";\n }\n\n const firstAuthor = item.author[0];\n if (!firstAuthor) {\n return \"Unknown\";\n }\n\n return firstAuthor.family || \"Unknown\";\n}\n\n/**\n * Format a single in-text citation (without parentheses)\n * Returns \"Family et al, YYYY\" or \"Family, YYYY\"\n */\nfunction formatInTextEntry(item: CslItem): string {\n const author = getFirstAuthorFamilyName(item);\n const etAl = hasMultipleAuthors(item) ? \" et al\" : \"\";\n const year = extractYear(item);\n\n return `${author}${etAl}, ${year}`;\n}\n\n/**\n * Format CSL-JSON items as simplified AMA-like bibliography entries.\n *\n * Format: FirstAuthor [et al]. JournalAbbrev. YYYY;volume(issue):pages. PMID:xxxxx [or DOI:xxxxx]. Title.\n *\n * Multiple items are separated by double newlines.\n *\n * @param items - Array of CSL-JSON items\n * @returns Formatted bibliography entries separated by double newlines\n */\nexport function formatBibliography(items: CslItem[]): string {\n if (items.length === 0) {\n return \"\";\n }\n\n return items.map(formatBibliographyEntry).join(\"\\n\\n\");\n}\n\n/**\n * Format CSL-JSON items as simplified in-text citations.\n *\n * Format: (FirstAuthor et al, YYYY)\n *\n * Multiple items are separated by semicolons and enclosed in parentheses.\n *\n * @param items - Array of CSL-JSON items\n * @returns Formatted in-text citation(s) enclosed in parentheses\n */\nexport function formatInText(items: CslItem[]): string {\n if (items.length === 0) {\n return \"\";\n }\n\n const citations = items.map(formatInTextEntry).join(\"; \");\n return `(${citations})`;\n}\n","import { Cite } from \"@citation-js/core\";\nimport \"@citation-js/plugin-csl\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport { formatBibliography, formatInText } from \"./citation-fallback.js\";\n\n/**\n * Options for CSL citation formatting\n */\nexport type CitationFormatOptions = {\n /**\n * CSL style name (e.g., 'apa', 'vancouver', 'chicago')\n * @default 'apa'\n */\n style?: string;\n\n /**\n * Output format: text, html, or rtf\n * @default 'text'\n */\n format?: \"text\" | \"html\" | \"rtf\";\n\n /**\n * Locale code (e.g., 'en-US', 'en-GB')\n * @default 'en-US'\n */\n locale?: string;\n};\n\n/**\n * Format CSL-JSON items as bibliography using CSL processor.\n * Falls back to simplified format if CSL processing fails.\n *\n * @param items - Array of CSL-JSON items\n * @param options - Formatting options\n * @returns Formatted bibliography entries\n */\nexport function formatBibliographyCSL(items: CslItem[], options: CitationFormatOptions): string {\n // Handle empty array\n if (items.length === 0) {\n return \"\";\n }\n\n // Set defaults\n const style = options.style || \"apa\";\n const format = options.format || \"text\";\n const locale = options.locale || \"en-US\";\n\n try {\n // Create Cite instance with CSL-JSON data\n const cite = new Cite(items);\n\n // Format as bibliography\n const result = cite.format(\"bibliography\", {\n format,\n template: style,\n lang: locale,\n });\n\n return result;\n } catch (error) {\n // Fall back to simplified format on any error\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(\n `Warning: CSL processing failed (style: ${style}), falling back to simplified format: ${errorMessage}\\n`\n );\n return formatBibliography(items);\n }\n}\n\n/**\n * Format CSL-JSON items as in-text citations using CSL processor.\n * Falls back to simplified format if CSL processing fails.\n *\n * @param items - Array of CSL-JSON items\n * @param options - Formatting options\n * @returns Formatted in-text citation(s)\n */\nexport function formatInTextCSL(items: CslItem[], options: CitationFormatOptions): string {\n // Handle empty array\n if (items.length === 0) {\n return \"\";\n }\n\n // Set defaults\n const style = options.style || \"apa\";\n const format = options.format || \"text\";\n const locale = options.locale || \"en-US\";\n\n try {\n // Create Cite instance with CSL-JSON data\n const cite = new Cite(items);\n\n // Format as in-text citation\n const result = cite.format(\"citation\", {\n format,\n template: style,\n lang: locale,\n });\n\n return result;\n } catch (error) {\n // Fall back to simplified format on any error\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(\n `Warning: CSL processing failed (style: ${style}), falling back to simplified format: ${errorMessage}\\n`\n );\n return formatInText(items);\n }\n}\n","import { isBuiltinStyle } from \"../../config/csl-styles.js\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../core/library-interface.js\";\nimport {\n formatBibliography,\n formatBibliographyCSL,\n formatInText,\n formatInTextCSL,\n} from \"../format/index.js\";\n\n/**\n * Options for citeReferences operation\n */\nexport interface CiteOperationOptions {\n /** Reference IDs or UUIDs to cite */\n identifiers: string[];\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType;\n /** CSL style name or path to CSL file */\n style?: string;\n /** Path to custom CSL file */\n cslFile?: string;\n /** Locale for citation formatting (default: \"en-US\") */\n locale?: string;\n /** Output format (default: \"text\") */\n format?: \"text\" | \"html\" | \"rtf\";\n /** If true, generate in-text citation instead of bibliography */\n inText?: boolean;\n}\n\n/**\n * Result for a single citation\n */\nexport type CiteItemResult =\n | { success: true; identifier: string; citation: string }\n | { success: false; identifier: string; error: string };\n\n/**\n * Result of citeReferences operation\n */\nexport interface CiteResult {\n /** Results for each identifier */\n results: CiteItemResult[];\n}\n\ninterface FormatOptions {\n style?: string | undefined;\n cslFile?: string | undefined;\n locale?: string | undefined;\n format?: \"text\" | \"html\" | \"rtf\" | undefined;\n}\n\n/**\n * Check if fallback formatter should be used.\n */\nfunction shouldUseFallback(options: FormatOptions): boolean {\n if (options.cslFile) {\n return false;\n }\n if (options.style && !isBuiltinStyle(options.style)) {\n return true;\n }\n return false;\n}\n\n/**\n * Format a single item as citation.\n */\nfunction formatCitation(item: CslItem, inText: boolean, options: FormatOptions): string {\n const useFallback = shouldUseFallback(options);\n const style = options.cslFile ?? options.style ?? \"apa\";\n const locale = options.locale ?? \"en-US\";\n const format = options.format ?? \"text\";\n\n if (useFallback) {\n return inText ? formatInText([item]) : formatBibliography([item]);\n }\n\n return inText\n ? formatInTextCSL([item], { style, locale, format })\n : formatBibliographyCSL([item], { style, locale, format });\n}\n\n/**\n * Generate citation for a single identifier.\n */\nasync function generateCitationForIdentifier(\n library: ILibrary,\n identifier: string,\n idType: IdentifierType,\n inText: boolean,\n options: FormatOptions\n): Promise<CiteItemResult> {\n const item = await library.find(identifier, { idType });\n\n if (!item) {\n const lookupType = idType === \"uuid\" ? \"UUID\" : idType.toUpperCase();\n return {\n success: false,\n identifier,\n error: `Reference with ${lookupType} '${identifier}' not found`,\n };\n }\n\n const citation = formatCitation(item, inText, options);\n\n return {\n success: true,\n identifier,\n citation,\n };\n}\n\n/**\n * Generate citations for references.\n *\n * @param library - The library to cite from\n * @param options - Citation options including identifiers and style settings\n * @returns Results array with citation or error for each identifier\n */\nexport async function citeReferences(\n library: ILibrary,\n options: CiteOperationOptions\n): Promise<CiteResult> {\n const { identifiers, idType = \"id\", inText = false, style, cslFile, locale, format } = options;\n const results: CiteItemResult[] = [];\n\n for (const identifier of identifiers) {\n const result = await generateCitationForIdentifier(library, identifier, idType, inText, {\n style,\n cslFile,\n locale,\n format,\n });\n results.push(result);\n }\n\n return { results };\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary } from \"../../core/library-interface.js\";\nimport { formatBibtex, formatPretty } from \"../format/index.js\";\n\n/**\n * Output format options for list operation\n */\nexport type ListFormat = \"pretty\" | \"json\" | \"bibtex\" | \"ids-only\" | \"uuid\";\n\n/**\n * Options for listReferences operation\n */\nexport interface ListOptions {\n /** Output format (default: \"pretty\") */\n format?: ListFormat;\n}\n\n/**\n * Result of listReferences operation\n */\nexport interface ListResult {\n /** Formatted strings for each reference */\n items: string[];\n}\n\n/**\n * List all references from the library with specified format.\n *\n * @param library - The library to list references from\n * @param options - Formatting options\n * @returns Formatted strings for each reference\n */\nexport async function listReferences(library: ILibrary, options: ListOptions): Promise<ListResult> {\n const format = options.format ?? \"pretty\";\n const items = await library.getAll();\n\n switch (format) {\n case \"json\":\n return { items: items.map((item) => JSON.stringify(item)) };\n\n case \"bibtex\":\n // Format each item individually using existing formatter\n return { items: items.map((item) => formatBibtex([item])) };\n\n case \"ids-only\":\n return { items: items.map((item) => item.id) };\n\n case \"uuid\":\n return {\n items: items\n .filter((item): item is CslItem & { custom: { uuid: string } } =>\n Boolean(item.custom?.uuid)\n )\n .map((item) => item.custom.uuid),\n };\n\n default:\n // Format each item individually using existing formatter (pretty)\n return { items: items.map((item) => formatPretty([item])) };\n }\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../core/library-interface.js\";\n\n/**\n * Options for removeReference operation\n */\nexport interface RemoveOperationOptions {\n /** Reference ID or UUID */\n identifier: string;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType;\n}\n\n/**\n * Result of removeReference operation\n */\nexport interface RemoveResult {\n /** Whether the reference was removed */\n removed: boolean;\n /** The removed item (if found and removal succeeded) */\n removedItem?: CslItem;\n}\n\n/**\n * Remove a reference from the library.\n *\n * @param library - The library to remove from\n * @param options - Remove options including identifier and lookup method\n * @returns Result indicating success and the removed item\n */\nexport async function removeReference(\n library: ILibrary,\n options: RemoveOperationOptions\n): Promise<RemoveResult> {\n const { identifier, idType = \"id\" } = options;\n\n const result = await library.remove(identifier, { idType });\n\n if (result.removed) {\n await library.save();\n }\n\n return result;\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary } from \"../../core/library-interface.js\";\nimport { formatBibtex, formatPretty } from \"../format/index.js\";\nimport { search } from \"../search/matcher.js\";\nimport { sortResults } from \"../search/sorter.js\";\nimport { tokenize } from \"../search/tokenizer.js\";\n\n/**\n * Output format options for search operation\n */\nexport type SearchFormat = \"pretty\" | \"json\" | \"bibtex\" | \"ids-only\" | \"uuid\";\n\n/**\n * Options for searchReferences operation\n */\nexport interface SearchOperationOptions {\n /** Search query string */\n query: string;\n /** Output format (default: \"pretty\") */\n format?: SearchFormat;\n}\n\n/**\n * Result of searchReferences operation\n */\nexport interface SearchResult {\n /** Formatted strings for each matching reference */\n items: string[];\n}\n\n/**\n * Search references in the library and return formatted results.\n *\n * @param library - The library to search in\n * @param options - Search query and formatting options\n * @returns Formatted strings for each matching reference\n */\nexport async function searchReferences(\n library: ILibrary,\n options: SearchOperationOptions\n): Promise<SearchResult> {\n const format = options.format ?? \"pretty\";\n const query = options.query;\n\n // Get all references\n const allItems = await library.getAll();\n\n // If query is empty, return all items\n let matchedItems: CslItem[];\n if (!query.trim()) {\n matchedItems = allItems;\n } else {\n // Tokenize and search\n const tokens = tokenize(query).tokens;\n const results = search(allItems, tokens);\n const sorted = sortResults(results);\n matchedItems = sorted.map((result) => result.reference);\n }\n\n // Format results based on format option\n switch (format) {\n case \"json\":\n return { items: matchedItems.map((item) => JSON.stringify(item)) };\n\n case \"bibtex\":\n return { items: matchedItems.map((item) => formatBibtex([item])) };\n\n case \"ids-only\":\n return { items: matchedItems.map((item) => item.id) };\n\n case \"uuid\":\n return {\n items: matchedItems\n .filter((item): item is CslItem & { custom: { uuid: string } } =>\n Boolean(item.custom?.uuid)\n )\n .map((item) => item.custom.uuid),\n };\n\n default:\n return { items: matchedItems.map((item) => formatPretty([item])) };\n }\n}\n","import { Hono } from \"hono\";\nimport type { Config } from \"../../config/schema.js\";\nimport type { Library } from \"../../core/library.js\";\nimport type { InputFormat } from \"../../features/import/detector.js\";\nimport type { PubmedConfig } from \"../../features/import/fetcher.js\";\nimport { type AddReferencesOptions, addReferences } from \"../../features/operations/add.js\";\n\n/**\n * Build PubmedConfig from config, filtering out undefined values\n * to satisfy exactOptionalPropertyTypes requirements.\n */\nfunction buildPubmedConfig(config: Config): PubmedConfig {\n const pubmedConfig: PubmedConfig = {};\n if (config.pubmed.email !== undefined) {\n pubmedConfig.email = config.pubmed.email;\n }\n if (config.pubmed.apiKey !== undefined) {\n pubmedConfig.apiKey = config.pubmed.apiKey;\n }\n return pubmedConfig;\n}\n\n/**\n * Create add route for importing references.\n * @param library - Library instance to use for operations\n * @param config - Configuration with PubMed settings\n * @returns Hono app with add route\n */\nexport function createAddRoute(library: Library, config: Config) {\n const route = new Hono();\n\n // POST / - Add references from inputs\n route.post(\"/\", async (c) => {\n // Parse request body\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n // Validate inputs\n if (!body || typeof body !== \"object\") {\n return c.json({ error: \"Request body must be an object\" }, 400);\n }\n\n const { inputs, options } = body as {\n inputs?: unknown;\n options?: { force?: boolean; format?: string };\n };\n\n if (!inputs || !Array.isArray(inputs) || inputs.length === 0) {\n return c.json({ error: \"inputs must be a non-empty array of strings\" }, 400);\n }\n\n // Ensure all inputs are strings\n if (!inputs.every((input) => typeof input === \"string\")) {\n return c.json({ error: \"All inputs must be strings\" }, 400);\n }\n\n // Build options\n const addOptions: AddReferencesOptions = {\n force: options?.force ?? false,\n pubmedConfig: buildPubmedConfig(config),\n };\n\n if (options?.format) {\n addOptions.format = options.format as InputFormat | \"auto\";\n }\n\n // Call addReferences\n const result = await addReferences(inputs as string[], library, addOptions);\n\n return c.json(result);\n });\n\n return route;\n}\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { Library } from \"../../core/library.js\";\nimport {\n type CiteOperationOptions,\n type CiteResult,\n citeReferences,\n} from \"../../features/operations/cite.js\";\n\n/**\n * Zod schema for cite request body\n */\nconst CiteRequestSchema = z.object({\n identifiers: z.array(z.string()).min(1, \"identifiers must be a non-empty array\"),\n idType: z.enum([\"id\", \"uuid\", \"doi\", \"pmid\", \"isbn\"]).optional(),\n inText: z.boolean().optional(),\n style: z.string().optional(),\n cslFile: z.string().optional(),\n locale: z.string().optional(),\n format: z.enum([\"text\", \"html\"]).optional(),\n});\n\ntype CiteRequestBody = z.infer<typeof CiteRequestSchema>;\n\n/**\n * Build cite operation options from validated request body.\n */\nfunction buildCiteOptions(body: CiteRequestBody): CiteOperationOptions {\n return {\n identifiers: body.identifiers,\n ...(body.idType !== undefined && { idType: body.idType }),\n ...(body.inText !== undefined && { inText: body.inText }),\n ...(body.style !== undefined && { style: body.style }),\n ...(body.cslFile !== undefined && { cslFile: body.cslFile }),\n ...(body.locale !== undefined && { locale: body.locale }),\n ...(body.format !== undefined && { format: body.format }),\n };\n}\n\n/**\n * Create cite route for generating citations.\n * @param library - Library instance to use for operations\n * @returns Hono app with cite route\n */\nexport function createCiteRoute(library: Library) {\n const route = new Hono();\n\n // POST / - Generate citations for identifiers\n route.post(\"/\", async (c) => {\n // Parse request body\n let rawBody: unknown;\n try {\n rawBody = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n // Validate with zod schema\n const parseResult = CiteRequestSchema.safeParse(rawBody);\n if (!parseResult.success) {\n const errorMessage = parseResult.error.issues[0]?.message ?? \"Invalid request body\";\n return c.json({ error: errorMessage }, 400);\n }\n\n // Call citeReferences operation\n const result: CiteResult = await citeReferences(library, buildCiteOptions(parseResult.data));\n\n return c.json(result);\n });\n\n return route;\n}\n","import { Hono } from \"hono\";\n\n/**\n * Health check route.\n * Returns a simple status to verify the server is running.\n */\nexport const healthRoute = new Hono();\n\nhealthRoute.get(\"/\", (c) => {\n return c.json({ status: \"ok\" });\n});\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { Library } from \"../../core/library.js\";\nimport { type ListOptions, listReferences } from \"../../features/operations/list.js\";\n\n/**\n * Request body schema for list endpoint\n */\nconst listRequestBodySchema = z.object({\n format: z.enum([\"pretty\", \"json\", \"bibtex\", \"ids-only\", \"uuid\"]).optional(),\n});\n\n/**\n * Request body type for list endpoint\n */\nexport type ListRequestBody = z.infer<typeof listRequestBodySchema>;\n\n/**\n * Creates list route for HTTP server\n */\nexport function createListRoute(library: Library) {\n const route = new Hono();\n\n // POST / - List all references\n route.post(\"/\", async (c) => {\n // Parse request body\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n // Validate body with zod\n const parseResult = listRequestBodySchema.safeParse(body);\n if (!parseResult.success) {\n return c.json({ error: \"Request body must be an object\" }, 400);\n }\n\n const requestBody = parseResult.data;\n\n // Build options for listReferences\n const options: ListOptions = {};\n if (requestBody.format !== undefined) {\n options.format = requestBody.format;\n }\n\n // Call listReferences operation\n const result = await listReferences(library, options);\n\n return c.json(result);\n });\n\n return route;\n}\n","import { Hono } from \"hono\";\nimport type { Library } from \"../../core/library.js\";\nimport { removeReference } from \"../../features/operations/remove.js\";\nimport { updateReference } from \"../../features/operations/update.js\";\n\n/**\n * Create references CRUD route with the given library.\n * @param library - Library instance to use for operations\n * @returns Hono app with references routes\n */\nexport function createReferencesRoute(library: Library) {\n const route = new Hono();\n\n // GET / - Get all references (getAll now returns Promise<CslItem[]>)\n route.get(\"/\", async (c) => {\n const items = await library.getAll();\n return c.json(items);\n });\n\n // GET /uuid/:uuid - Get reference by UUID\n route.get(\"/uuid/:uuid\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n const item = await library.find(uuid, { idType: \"uuid\" });\n\n if (!item) {\n return c.json({ error: \"Reference not found\" }, 404);\n }\n\n return c.json(item);\n });\n\n // GET /id/:id - Get reference by citation ID\n route.get(\"/id/:id\", async (c) => {\n const id = c.req.param(\"id\");\n const item = await library.find(id);\n\n if (!item) {\n return c.json({ error: \"Reference not found\" }, 404);\n }\n\n return c.json(item);\n });\n\n // POST / - Create new reference\n route.post(\"/\", async (c) => {\n try {\n const body = await c.req.json();\n\n // Create and add reference (library.add handles validation and returns the added item)\n const addedItem = await library.add(body);\n\n return c.json(addedItem, 201);\n } catch (error) {\n return c.json(\n {\n error: \"Invalid request body\",\n details: error instanceof Error ? error.message : String(error),\n },\n 400\n );\n }\n });\n\n // PUT /uuid/:uuid - Update reference by UUID\n // Request body: { updates: Partial<CslItem>, onIdCollision?: \"fail\" | \"suffix\" }\n route.put(\"/uuid/:uuid\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n if (!body || typeof body !== \"object\") {\n return c.json({ error: \"Request body must be an object\" }, 400);\n }\n\n const { updates, onIdCollision } = body as {\n updates?: Partial<import(\"../../core/csl-json/types.js\").CslItem>;\n onIdCollision?: \"fail\" | \"suffix\";\n };\n\n if (!updates || typeof updates !== \"object\") {\n return c.json({ error: \"Request body must contain 'updates' object\" }, 400);\n }\n\n // Use updateReference operation\n const result = await updateReference(library, {\n identifier: uuid,\n idType: \"uuid\",\n updates,\n onIdCollision: onIdCollision ?? \"suffix\",\n });\n\n // Return operation result with appropriate status code\n if (!result.updated) {\n const status = result.idCollision ? 409 : 404;\n return c.json(result, status);\n }\n\n return c.json(result);\n });\n\n // PUT /id/:id - Update reference by citation ID\n // Request body: { updates: Partial<CslItem>, onIdCollision?: \"fail\" | \"suffix\" }\n route.put(\"/id/:id\", async (c) => {\n const id = c.req.param(\"id\");\n\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n if (!body || typeof body !== \"object\") {\n return c.json({ error: \"Request body must be an object\" }, 400);\n }\n\n const { updates, onIdCollision } = body as {\n updates?: Partial<import(\"../../core/csl-json/types.js\").CslItem>;\n onIdCollision?: \"fail\" | \"suffix\";\n };\n\n if (!updates || typeof updates !== \"object\") {\n return c.json({ error: \"Request body must contain 'updates' object\" }, 400);\n }\n\n // Use updateReference operation with idType: 'id'\n const result = await updateReference(library, {\n identifier: id,\n updates,\n onIdCollision: onIdCollision ?? \"suffix\",\n });\n\n // Return operation result with appropriate status code\n if (!result.updated) {\n const status = result.idCollision ? 409 : 404;\n return c.json(result, status);\n }\n\n return c.json(result);\n });\n\n // DELETE /uuid/:uuid - Delete reference by UUID\n route.delete(\"/uuid/:uuid\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n\n // Use removeReference operation\n const result = await removeReference(library, {\n identifier: uuid,\n idType: \"uuid\",\n });\n\n // Return operation result with appropriate status code\n if (!result.removed) {\n return c.json(result, 404);\n }\n\n return c.json(result);\n });\n\n // DELETE /id/:id - Delete reference by citation ID\n route.delete(\"/id/:id\", async (c) => {\n const id = c.req.param(\"id\");\n\n // Use removeReference operation\n const result = await removeReference(library, {\n identifier: id,\n });\n\n // Return operation result with appropriate status code\n if (!result.removed) {\n return c.json(result, 404);\n }\n\n return c.json(result);\n });\n\n return route;\n}\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { Library } from \"../../core/library.js\";\nimport { type SearchOperationOptions, searchReferences } from \"../../features/operations/search.js\";\n\n/**\n * Request body schema for search endpoint\n */\nconst searchRequestBodySchema = z.object({\n query: z.string(),\n format: z.enum([\"pretty\", \"json\", \"bibtex\", \"ids-only\", \"uuid\"]).optional(),\n});\n\n/**\n * Request body type for search endpoint\n */\nexport type SearchRequestBody = z.infer<typeof searchRequestBodySchema>;\n\n/**\n * Creates search route for HTTP server\n */\nexport function createSearchRoute(library: Library) {\n const route = new Hono();\n\n // POST / - Search references\n route.post(\"/\", async (c) => {\n // Parse request body\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n // Validate body with zod\n const parseResult = searchRequestBodySchema.safeParse(body);\n if (!parseResult.success) {\n return c.json({ error: \"Invalid request body\" }, 400);\n }\n\n const requestBody = parseResult.data;\n\n // Build options for searchReferences\n const options: SearchOperationOptions = {\n query: requestBody.query,\n };\n if (requestBody.format !== undefined) {\n options.format = requestBody.format;\n }\n\n // Call searchReferences operation\n const result = await searchReferences(library, options);\n\n return c.json(result);\n });\n\n return route;\n}\n","import { Hono } from \"hono\";\nimport type { Config } from \"../config/schema.js\";\nimport { Library } from \"../core/library.js\";\nimport { FileWatcher } from \"../features/file-watcher/file-watcher.js\";\nimport { createAddRoute } from \"./routes/add.js\";\nimport { createCiteRoute } from \"./routes/cite.js\";\nimport { healthRoute } from \"./routes/health.js\";\nimport { createListRoute } from \"./routes/list.js\";\nimport { createReferencesRoute } from \"./routes/references.js\";\nimport { createSearchRoute } from \"./routes/search.js\";\n\n/**\n * Result of starting a server with file watcher.\n */\nexport interface ServerWithFileWatcherResult {\n /** The Hono application */\n app: Hono;\n /** The library instance */\n library: Library;\n /** The file watcher instance */\n fileWatcher: FileWatcher;\n /** Dispose function to clean up resources */\n dispose: () => Promise<void>;\n}\n\n/**\n * Create the main Hono server application.\n * @param library - Library instance for the references API\n * @param config - Configuration for the server\n * @returns Hono application\n */\nexport function createServer(library: Library, config: Config) {\n const app = new Hono();\n\n // Health check route\n app.route(\"/health\", healthRoute);\n\n // References API routes\n const referencesRoute = createReferencesRoute(library);\n app.route(\"/api/references\", referencesRoute);\n\n // Add references route\n const addRoute = createAddRoute(library, config);\n app.route(\"/api/add\", addRoute);\n\n // Cite route\n const citeRoute = createCiteRoute(library);\n app.route(\"/api/cite\", citeRoute);\n\n // List route\n const listRoute = createListRoute(library);\n app.route(\"/api/list\", listRoute);\n\n // Search route\n const searchRoute = createSearchRoute(library);\n app.route(\"/api/search\", searchRoute);\n\n return app;\n}\n\n/**\n * Start a server with file watcher for automatic library reload.\n * Uses the same pattern as MCP server file monitoring.\n * @param libraryPath - Path to the library file\n * @param config - Configuration for the server\n * @returns Server with file watcher result\n */\nexport async function startServerWithFileWatcher(\n libraryPath: string,\n config: Config\n): Promise<ServerWithFileWatcherResult> {\n // Load library\n const library = await Library.load(libraryPath);\n\n // Create the Hono app\n const app = createServer(library, config);\n\n // Create and start file watcher\n const fileWatcher = new FileWatcher(libraryPath, {\n debounceMs: config.watch.debounceMs,\n maxRetries: config.watch.maxRetries,\n retryDelayMs: config.watch.retryIntervalMs,\n pollIntervalMs: config.watch.pollIntervalMs,\n });\n\n // Listen for file changes\n // Library.reload() handles self-write detection via hash comparison\n fileWatcher.on(\"change\", () => {\n library.reload().catch((error) => {\n // Log error but don't crash - library continues with previous state\n console.error(\"Failed to reload library:\", error);\n });\n });\n\n await fileWatcher.start();\n\n // Create dispose function\n const dispose = async (): Promise<void> => {\n fileWatcher.close();\n };\n\n return {\n app,\n library,\n fileWatcher,\n dispose,\n };\n}\n"],"names":["result","DOI_URL_PREFIXES","cite","identifiers","search"],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Uses ILibrary interface for unified operations across local and server modes.
5
5
  */
6
+ import type { IdentifierType } from "../../core/library-interface.js";
6
7
  import type { FulltextType } from "../../features/fulltext/index.js";
7
8
  import { type FulltextAttachResult, type FulltextDetachResult, type FulltextGetResult } from "../../features/operations/fulltext/index.js";
8
9
  import type { ExecutionContext } from "../execution-context.js";
@@ -15,7 +16,7 @@ export interface FulltextAttachOptions {
15
16
  type?: FulltextType;
16
17
  move?: boolean;
17
18
  force?: boolean;
18
- byUuid?: boolean;
19
+ idType?: IdentifierType;
19
20
  fulltextDirectory: string;
20
21
  stdinContent?: Buffer;
21
22
  }
@@ -26,7 +27,7 @@ export interface FulltextGetOptions {
26
27
  identifier: string;
27
28
  type?: FulltextType;
28
29
  stdout?: boolean;
29
- byUuid?: boolean;
30
+ idType?: IdentifierType;
30
31
  fulltextDirectory: string;
31
32
  }
32
33
  /**
@@ -37,7 +38,7 @@ export interface FulltextDetachOptions {
37
38
  type?: FulltextType;
38
39
  delete?: boolean;
39
40
  force?: boolean;
40
- byUuid?: boolean;
41
+ idType?: IdentifierType;
41
42
  fulltextDirectory: string;
42
43
  }
43
44
  export type { FulltextAttachResult, FulltextGetResult, FulltextDetachResult };
@@ -1 +1 @@
1
- {"version":3,"file":"fulltext.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/fulltext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EAOvB,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAGD,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,CAAC;AAE9E;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAa/B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,iBAAiB,CAAC,CAU5B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAMD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAiB/E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAkBzE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAe/E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,oBAAoB,GAAG,iBAAiB,GAAG,oBAAoB,GACtE,MAAM,CAER"}
1
+ {"version":3,"file":"fulltext.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/fulltext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EAOvB,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAGD,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,CAAC;AAE9E;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAa/B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,iBAAiB,CAAC,CAU5B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAMD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAiB/E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAkBzE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAe/E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,oBAAoB,GAAG,iBAAiB,GAAG,oBAAoB,GACtE,MAAM,CAER"}
@@ -1,4 +1,5 @@
1
1
  import type { CslItem } from "../../core/csl-json/types.js";
2
+ import type { IdentifierType } from "../../core/library-interface.js";
2
3
  import type { FulltextType } from "../../features/fulltext/index.js";
3
4
  import type { RemoveResult } from "../../features/operations/remove.js";
4
5
  import type { ExecutionContext } from "../execution-context.js";
@@ -7,7 +8,7 @@ import type { ExecutionContext } from "../execution-context.js";
7
8
  */
8
9
  export interface RemoveCommandOptions {
9
10
  identifier: string;
10
- byUuid?: boolean;
11
+ idType?: IdentifierType;
11
12
  }
12
13
  /**
13
14
  * Result from remove command execution.
@@ -1 +1 @@
1
- {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/remove.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAI9B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAW1F;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,EAAE,CAYxE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,CAInE;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBjG"}
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/remove.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAI9B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAW1F;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,EAAE,CAYxE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,CAInE;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBjG"}
@@ -1,4 +1,5 @@
1
1
  import type { CslItem } from "../../core/csl-json/types.js";
2
+ import type { IdentifierType } from "../../core/library-interface.js";
2
3
  import type { UpdateOperationResult } from "../../features/operations/update.js";
3
4
  import type { ExecutionContext } from "../execution-context.js";
4
5
  /**
@@ -7,7 +8,7 @@ import type { ExecutionContext } from "../execution-context.js";
7
8
  export interface UpdateCommandOptions {
8
9
  identifier: string;
9
10
  updates: Partial<CslItem>;
10
- byUuid?: boolean;
11
+ idType?: IdentifierType;
11
12
  }
12
13
  /**
13
14
  * Result from update command execution.
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAI9B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAsB1F"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAI9B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAsB1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoDpC;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CA8BvC;AAmwBD;;GAEG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAaxD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoDpC;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CA8BvC;AAuwBD;;GAEG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAaxD"}
@@ -1,12 +1,13 @@
1
1
  import type { CslItem } from "../core/csl-json/types.js";
2
2
  import type { FindOptions, RemoveResult as ILibraryRemoveResult, RemoveOptions, UpdateOptions, UpdateResult } from "../core/library-interface.js";
3
3
  import type { AddReferencesResult, CiteResult, ILibraryOperations, ImportOptions, ListOptions, ListResult, SearchOperationOptions, SearchResult } from "../features/operations/index.js";
4
+ import type { IdentifierType } from "../core/library-interface.js";
4
5
  /**
5
6
  * Options for cite method.
6
7
  */
7
8
  export interface CiteOptions {
8
9
  identifiers: string[];
9
- byUuid?: boolean;
10
+ idType?: IdentifierType;
10
11
  inText?: boolean;
11
12
  style?: string;
12
13
  cslFile?: string;
@@ -27,7 +28,7 @@ export declare class ServerClient implements ILibraryOperations {
27
28
  /**
28
29
  * Find reference by citation ID or UUID.
29
30
  * @param identifier - Citation ID or UUID
30
- * @param options - Find options (byUuid to use UUID lookup)
31
+ * @param options - Find options (idType to specify identifier type)
31
32
  * @returns CSL item or undefined if not found
32
33
  */
33
34
  find(identifier: string, options?: FindOptions): Promise<CslItem | undefined>;
@@ -41,14 +42,14 @@ export declare class ServerClient implements ILibraryOperations {
41
42
  * Update reference by citation ID or UUID.
42
43
  * @param identifier - Citation ID or UUID
43
44
  * @param updates - Partial CSL item with fields to update
44
- * @param options - Update options (byUuid to use UUID lookup, onIdCollision for collision handling)
45
+ * @param options - Update options (idType to specify identifier type, onIdCollision for collision handling)
45
46
  * @returns Update result with updated item, success status, and any ID changes
46
47
  */
47
48
  update(identifier: string, updates: Partial<CslItem>, options?: UpdateOptions): Promise<UpdateResult>;
48
49
  /**
49
50
  * Remove a reference by citation ID or UUID.
50
51
  * @param identifier - The citation ID or UUID of the reference to remove
51
- * @param options - Remove options (byUuid to use UUID lookup)
52
+ * @param options - Remove options (idType to specify identifier type)
52
53
  * @returns Remove result with removed status and removedItem
53
54
  */
54
55
  remove(identifier: string, options?: RemoveOptions): Promise<ILibraryRemoveResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"server-client.d.ts","sourceRoot":"","sources":["../../src/cli/server-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EACV,WAAW,EACX,YAAY,IAAI,oBAAoB,EACpC,aAAa,EACb,aAAa,EACb,YAAY,EACb,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,mBAAmB,EACnB,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,UAAU,EACV,sBAAsB,EACtB,YAAY,EACb,MAAM,iCAAiC,CAAC;AAIzC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,qBAAa,YAAa,YAAW,kBAAkB;IACzC,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,MAAM;IAMnC;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAWlC;;;;;OAKG;IACG,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAsBvF;;;;OAIG;IACG,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB1C;;;;;;OAMG;IACG,MAAM,CACV,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EACzB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC;IA0BxB;;;;;OAKG;IACG,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAyB5F;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAerF;;;;OAIG;IACG,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAerD;;;;OAIG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAetD;;;;OAIG;IACG,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC;CAcrE"}
1
+ {"version":3,"file":"server-client.d.ts","sourceRoot":"","sources":["../../src/cli/server-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EACV,WAAW,EACX,YAAY,IAAI,oBAAoB,EACpC,aAAa,EACb,aAAa,EACb,YAAY,EACb,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,mBAAmB,EACnB,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,UAAU,EACV,sBAAsB,EACtB,YAAY,EACb,MAAM,iCAAiC,CAAC;AAIzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,qBAAa,YAAa,YAAW,kBAAkB;IACzC,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,MAAM;IAMnC;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAWlC;;;;;OAKG;IACG,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAuBvF;;;;OAIG;IACG,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB1C;;;;;;OAMG;IACG,MAAM,CACV,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EACzB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC;IA2BxB;;;;;OAKG;IACG,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA0B5F;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAerF;;;;OAIG;IACG,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAerD;;;;OAIG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAetD;;;;OAIG;IACG,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC;CAcrE"}