{"version":3,"file":"helpers.mjs","names":[],"sources":["../../src/helpers.ts"],"sourcesContent":["import type { Package, Version, Dependency, Maintainer, URLBuilder } from \"./core/types.ts\";\nimport type { Client } from \"./core/client.ts\";\nimport { createFromPURL } from \"./core/purl.ts\";\nimport { InvalidPURLError } from \"./core/errors.ts\";\n\n/**\n * Fetch normalized package metadata from a package URL.\n *\n * @param purl - Package URL.\n * @param signal - Optional cancellation signal.\n * @param client - Optional HTTP client.\n * @returns {Promise<Package>} Normalized package metadata.\n */\nexport async function fetchPackageFromPURL(\n  purl: string,\n  signal?: AbortSignal,\n  client?: Client,\n): Promise<Package> {\n  const [reg, name] = await createFromPURL(purl, client);\n  return reg.fetchPackage(name, signal);\n}\n\n/**\n * Fetch all versions from a package URL.\n *\n * @param purl - Package URL.\n * @param signal - Optional cancellation signal.\n * @param client - Optional HTTP client.\n * @returns {Promise<Version[]>} Normalized versions.\n */\nexport async function fetchVersionsFromPURL(\n  purl: string,\n  signal?: AbortSignal,\n  client?: Client,\n): Promise<Version[]> {\n  const [reg, name] = await createFromPURL(purl, client);\n  return reg.fetchVersions(name, signal);\n}\n\n/**\n * Fetch dependencies for a versioned package URL.\n *\n * @param purl - Versioned package URL.\n * @param signal - Optional cancellation signal.\n * @param client - Optional HTTP client.\n * @returns {Promise<Dependency[]>} Normalized dependencies.\n */\nexport async function fetchDependenciesFromPURL(\n  purl: string,\n  signal?: AbortSignal,\n  client?: Client,\n): Promise<Dependency[]> {\n  const [reg, name, version] = await createFromPURL(purl, client);\n  if (!version) {\n    throw new InvalidPURLError(purl, \"must include a version for dependency lookup\");\n  }\n  return reg.fetchDependencies(name, version, signal);\n}\n\n/**\n * Fetch maintainers from a package URL.\n *\n * @param purl - Package URL.\n * @param signal - Optional cancellation signal.\n * @param client - Optional HTTP client.\n * @returns {Promise<Maintainer[]>} Normalized maintainers.\n */\nexport async function fetchMaintainersFromPURL(\n  purl: string,\n  signal?: AbortSignal,\n  client?: Client,\n): Promise<Maintainer[]> {\n  const [reg, name] = await createFromPURL(purl, client);\n  return reg.fetchMaintainers(name, signal);\n}\n\nconst DEFAULT_CONCURRENCY = 15;\n\n/**\n * Fetch packages concurrently, skipping failed lookups.\n *\n * @param purls - Package URLs to fetch.\n * @param options - Optional concurrency, cancellation, and client settings.\n * @returns {Promise<Map<string, Package>>} Results keyed by package URL.\n */\nexport async function bulkFetchPackages(\n  purls: readonly string[],\n  options?: Readonly<{ concurrency?: number; signal?: AbortSignal; client?: Client }>,\n): Promise<Map<string, Package>> {\n  const concurrency = options?.concurrency ?? DEFAULT_CONCURRENCY;\n  const results = new Map<string, Package>();\n  const queue = [...purls];\n\n  const signal = options?.signal;\n\n  const workers = Array.from({ length: Math.min(concurrency, queue.length) }, async () => {\n    while (queue.length > 0) {\n      if (signal?.aborted) break;\n\n      const purl = queue.shift()!;\n      try {\n        const pkg = await fetchPackageFromPURL(purl, signal, options?.client);\n        results.set(purl, pkg);\n      } catch {\n        if (signal?.aborted) break;\n        // Silently skip failed lookups — absent from results map\n      }\n    }\n  });\n\n  await Promise.all(workers);\n  return results;\n}\n\n/**\n * Select an exact requested or latest version, then the newest usable one.\n *\n * @param versions - Candidate versions.\n * @param options - Optional requested and latest version numbers.\n * @returns {Version | null} The selected version, or null.\n */\nexport function selectVersion(\n  versions: readonly Version[],\n  options?: Readonly<{\n    requested?: string;\n    latest?: string;\n  }>,\n): Version | null {\n  const { requested, latest } = options ?? {};\n\n  if (requested) {\n    const exact = versions.find((v) => v.number === requested && v.status === \"\");\n    if (exact) return exact;\n  }\n\n  if (latest) {\n    const latestV = versions.find((v) => v.number === latest && v.status === \"\");\n    if (latestV) return latestV;\n  }\n\n  const usable = versions.filter((v) => v.status === \"\");\n  if (usable.length === 0) return null;\n\n  usable.sort((a, b) => {\n    const at = a.publishedAt?.getTime() ?? 0;\n    const bt = b.publishedAt?.getTime() ?? 0;\n    return bt - at;\n  });\n\n  return usable[0] ?? null;\n}\n\n/**\n * Resolve the best documentation URL for a package.\n *\n * @param pkg - Package metadata.\n * @param urls - Ecosystem URL builder.\n * @param version - Optional package version.\n * @returns {string} The explicit, homepage, or ecosystem documentation URL.\n */\nexport function resolveDocsUrl(pkg: Package, urls: URLBuilder, version?: string): string {\n  return pkg.documentation || pkg.homepage || urls.documentation(pkg.name, version);\n}\n\n/**\n * Resolve the ecosystem README URL for a package.\n *\n * @param pkg - Package metadata.\n * @param urls - Ecosystem URL builder.\n * @param version - Optional package version.\n * @returns {string} The README URL.\n */\nexport function resolveReadmeUrl(pkg: Package, urls: URLBuilder, version?: string): string {\n  return urls.readme(pkg.name, version);\n}\n"],"mappings":";;;;;;;;;;AAaA,eAAsB,qBACpB,MACA,QACA,QACkB;CAClB,MAAM,CAAC,KAAK,QAAQ,MAAM,eAAe,MAAM,OAAO;AACtD,QAAO,IAAI,aAAa,MAAM,OAAO;;;;;;;;;;AAWvC,eAAsB,sBACpB,MACA,QACA,QACoB;CACpB,MAAM,CAAC,KAAK,QAAQ,MAAM,eAAe,MAAM,OAAO;AACtD,QAAO,IAAI,cAAc,MAAM,OAAO;;;;;;;;;;AAWxC,eAAsB,0BACpB,MACA,QACA,QACuB;CACvB,MAAM,CAAC,KAAK,MAAM,WAAW,MAAM,eAAe,MAAM,OAAO;AAC/D,KAAI,CAAC,QACH,OAAM,IAAI,iBAAiB,MAAM,+CAA+C;AAElF,QAAO,IAAI,kBAAkB,MAAM,SAAS,OAAO;;;;;;;;;;AAWrD,eAAsB,yBACpB,MACA,QACA,QACuB;CACvB,MAAM,CAAC,KAAK,QAAQ,MAAM,eAAe,MAAM,OAAO;AACtD,QAAO,IAAI,iBAAiB,MAAM,OAAO;;AAG3C,MAAM,sBAAsB;;;;;;;;AAS5B,eAAsB,kBACpB,OACA,SAC+B;CAC/B,MAAM,cAAc,SAAS,eAAe;CAC5C,MAAM,0BAAU,IAAI,KAAsB;CAC1C,MAAM,QAAQ,CAAC,GAAG,MAAM;CAExB,MAAM,SAAS,SAAS;CAExB,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,aAAa,MAAM,OAAO,EAAE,EAAE,YAAY;AACtF,SAAO,MAAM,SAAS,GAAG;AACvB,OAAI,QAAQ,QAAS;GAErB,MAAM,OAAO,MAAM,OAAO;AAC1B,OAAI;IACF,MAAM,MAAM,MAAM,qBAAqB,MAAM,QAAQ,SAAS,OAAO;AACrE,YAAQ,IAAI,MAAM,IAAI;WAChB;AACN,QAAI,QAAQ,QAAS;;;GAIzB;AAEF,OAAM,QAAQ,IAAI,QAAQ;AAC1B,QAAO;;;;;;;;;AAUT,SAAgB,cACd,UACA,SAIgB;CAChB,MAAM,EAAE,WAAW,WAAW,WAAW,EAAE;AAE3C,KAAI,WAAW;EACb,MAAM,QAAQ,SAAS,MAAM,MAAM,EAAE,WAAW,aAAa,EAAE,WAAW,GAAG;AAC7E,MAAI,MAAO,QAAO;;AAGpB,KAAI,QAAQ;EACV,MAAM,UAAU,SAAS,MAAM,MAAM,EAAE,WAAW,UAAU,EAAE,WAAW,GAAG;AAC5E,MAAI,QAAS,QAAO;;CAGtB,MAAM,SAAS,SAAS,QAAQ,MAAM,EAAE,WAAW,GAAG;AACtD,KAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAO,MAAM,GAAG,MAAM;EACpB,MAAM,KAAK,EAAE,aAAa,SAAS,IAAI;AAEvC,UADW,EAAE,aAAa,SAAS,IAAI,KAC3B;GACZ;AAEF,QAAO,OAAO,MAAM;;;;;;;;;;AAWtB,SAAgB,eAAe,KAAc,MAAkB,SAA0B;AACvF,QAAO,IAAI,iBAAiB,IAAI,YAAY,KAAK,cAAc,IAAI,MAAM,QAAQ;;;;;;;;;;AAWnF,SAAgB,iBAAiB,KAAc,MAAkB,SAA0B;AACzF,QAAO,KAAK,OAAO,IAAI,MAAM,QAAQ"}