{
  "version": 3,
  "sources": ["../../../../src/packages/npm-resolver/pickPackage.ts"],
  "sourcesContent": ["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { createHexHash } from '../crypto.hash/index.ts';\nimport { PnpmError } from '../error/index.ts';\nimport { logger } from '../logger/index.ts';\nimport gfs from '../graceful-fs/index.ts';\nimport type { VersionSelectors } from '../resolver-base/index.ts';\nimport type { PackageManifest } from '../types/index.ts';\nimport getRegistryName from 'encode-registry';\nimport { loadJsonFile } from 'load-json-file';\nimport pLimit, { type LimitFunction } from 'p-limit';\nimport { fastPathTemp as pathTemp } from 'path-temp';\nimport pick from 'ramda/src/pick';\nimport semver from 'semver';\nimport renameOverwrite from 'rename-overwrite';\nimport { toRaw } from './toRaw.ts';\nimport {\n  pickPackageFromMeta,\n  pickVersionByVersionRange,\n  pickLowestVersionByVersionRange,\n} from './pickPackageFromMeta.ts';\nimport type { RegistryPackageSpec } from './parsePref.ts';\n\nexport type PackageMeta = {\n  name: string;\n  'dist-tags': Record<string, string>;\n  versions?: Record<string, PackageInRegistry> | undefined;\n  time?: PackageMetaTime | undefined;\n  cachedAt?: number | undefined;\n};\n\nexport type PackageMetaTime = Record<string, string> & {\n  unpublished?:\n    | {\n        time: string;\n        versions: string[];\n      }\n    | undefined;\n};\n\nexport type PackageMetaCache = {\n  get: (key: string) => PackageMeta | undefined;\n  set: (key: string, meta: PackageMeta) => void;\n  has: (key: string) => boolean;\n};\n\nexport interface PackageInRegistry extends PackageManifest {\n  hasInstallScript?: boolean | undefined;\n  dist: {\n    integrity?: string | undefined;\n    shasum: string;\n    tarball: string;\n  };\n}\n\ninterface RefCountedLimiter {\n  count: number;\n  limit: LimitFunction;\n}\n\n/**\n * prevents simultaneous operations on the meta.json\n * otherwise it would cause EPERM exceptions\n */\nconst metafileOperationLimits = {} as {\n  [pkgMirror: string]: RefCountedLimiter | undefined;\n};\n\n/**\n * To prevent metafileOperationLimits from holding onto objects in memory on\n * the order of the number of packages, refcount the limiters and drop them\n * once they are no longer needed. Callers of this function should ensure\n * that the limiter is no longer referenced once fn's Promise has resolved.\n */\nasync function runLimited<T>(\n  pkgMirror: string,\n  fn: (limit: LimitFunction) => Promise<T>\n): Promise<T> {\n  let entry: RefCountedLimiter | undefined;\n\n  try {\n    entry = metafileOperationLimits[pkgMirror] ??= {\n      count: 0,\n      limit: pLimit(1),\n    };\n    entry.count++;\n    return await fn(entry.limit);\n  } finally {\n    if (typeof entry === 'undefined') {\n      entry = {\n        count: 0,\n        limit: pLimit(1),\n      };\n    }\n\n    entry.count--;\n\n    if (entry.count === 0) {\n      metafileOperationLimits[pkgMirror] = undefined;\n    }\n  }\n}\n\nexport type PickPackageOptions = {\n  authHeaderValue?: string | undefined;\n  publishedBy?: Date | undefined;\n  preferredVersionSelectors?: VersionSelectors | undefined;\n  pickLowestVersion?: boolean | undefined;\n  registry: string;\n  dryRun: boolean;\n  updateToLatest?: boolean | undefined;\n};\n\nfunction pickPackageFromMetaUsingTime(\n  spec: RegistryPackageSpec,\n  preferredVersionSelectors: VersionSelectors | undefined,\n  meta: PackageMeta,\n  publishedBy?: Date | undefined\n): PackageInRegistry | undefined {\n  const pickedPackage = pickPackageFromMeta(\n    pickVersionByVersionRange,\n    spec,\n    preferredVersionSelectors,\n    meta,\n    publishedBy\n  );\n\n  if (pickedPackage) {\n    return pickedPackage;\n  }\n\n  return pickPackageFromMeta(\n    pickLowestVersionByVersionRange,\n    spec,\n    preferredVersionSelectors,\n    meta,\n    publishedBy\n  );\n}\n\nexport async function pickPackage(\n  ctx: {\n    fetch: (\n      pkgName: string,\n      registry: string,\n      authHeaderValue?: string | undefined\n    ) => Promise<PackageMeta>;\n    metaDir: string;\n    metaCache: PackageMetaCache;\n    cacheDir: string;\n    offline?: boolean | undefined;\n    preferOffline?: boolean | undefined;\n    filterMetadata?: boolean | undefined;\n  },\n  spec: RegistryPackageSpec,\n  opts?: PickPackageOptions | undefined\n): Promise<{\n  meta: PackageMeta;\n  pickedPackage?: PackageInRegistry | undefined;\n}> {\n  const newOpts = opts;\n\n  let _pickPackageFromMeta =\n    typeof newOpts?.publishedBy === 'undefined'\n      ? pickPackageFromMeta.bind(\n          null,\n          newOpts?.pickLowestVersion === true\n            ? pickLowestVersionByVersionRange\n            : pickVersionByVersionRange\n        )\n      : pickPackageFromMetaUsingTime;\n\n  if (newOpts?.updateToLatest === true) {\n    const _pickPackageBase = _pickPackageFromMeta;\n    _pickPackageFromMeta = (spec, ...rest) => {\n      const latestStableSpec: RegistryPackageSpec = {\n        ...spec,\n        type: 'tag',\n        fetchSpec: 'latest',\n      };\n      const latestStable = _pickPackageBase(latestStableSpec, ...rest);\n      const current = _pickPackageBase(spec, ...rest);\n\n      if (!latestStable) return current;\n      if (!current) return latestStable;\n      if (semver.lt(latestStable.version, current.version)) return current;\n      return latestStable;\n    };\n  }\n\n  validatePackageName(spec.name);\n\n  const cachedMeta = ctx.metaCache.get(spec.name);\n  if (cachedMeta != null) {\n    return {\n      meta: cachedMeta,\n      pickedPackage: _pickPackageFromMeta(\n        spec,\n        newOpts?.preferredVersionSelectors,\n        cachedMeta,\n        newOpts?.publishedBy\n      ),\n    };\n  }\n\n  const registryName = getRegistryName(newOpts?.registry ?? '');\n\n  const pkgMirror = path.join(\n    ctx.cacheDir,\n    ctx.metaDir,\n    registryName,\n    `${encodePkgName(spec.name)}.json`\n  );\n\n  return runLimited(pkgMirror, async (limit) => {\n    let metaCachedInStore: PackageMeta | null | undefined;\n    if (\n      ctx.offline === true ||\n      ctx.preferOffline === true ||\n      newOpts?.pickLowestVersion === true\n    ) {\n      metaCachedInStore = await limit(async () => loadMeta(pkgMirror));\n\n      if (ctx.offline === true) {\n        if (metaCachedInStore != null)\n          return {\n            meta: metaCachedInStore,\n            pickedPackage: _pickPackageFromMeta(\n              spec,\n              newOpts?.preferredVersionSelectors,\n              metaCachedInStore,\n              newOpts?.publishedBy\n            ),\n          };\n\n        throw new PnpmError(\n          'NO_OFFLINE_META',\n          `Failed to resolve ${toRaw(spec)} in package mirror ${pkgMirror}`\n        );\n      }\n\n      if (metaCachedInStore != null) {\n        const pickedPackage = _pickPackageFromMeta(\n          spec,\n          newOpts?.preferredVersionSelectors,\n          metaCachedInStore,\n          newOpts?.publishedBy\n        );\n\n        if (pickedPackage) {\n          return {\n            meta: metaCachedInStore,\n            pickedPackage,\n          };\n        }\n      }\n    }\n\n    if (newOpts?.updateToLatest !== true && spec.type === 'version') {\n      metaCachedInStore =\n        metaCachedInStore ?? (await limit(async () => loadMeta(pkgMirror)));\n      // use the cached meta only if it has the required package version\n      // otherwise it is probably out of date\n      if (metaCachedInStore?.versions?.[spec.fetchSpec] != null) {\n        return {\n          meta: metaCachedInStore,\n          pickedPackage: metaCachedInStore.versions[spec.fetchSpec],\n        };\n      }\n    }\n    if (newOpts?.publishedBy) {\n      metaCachedInStore =\n        metaCachedInStore ?? (await limit(async () => loadMeta(pkgMirror)));\n      if (\n        typeof metaCachedInStore?.cachedAt === 'number' &&\n        new Date(metaCachedInStore.cachedAt) >= newOpts.publishedBy\n      ) {\n        const pickedPackage = _pickPackageFromMeta(\n          spec,\n          newOpts.preferredVersionSelectors,\n          metaCachedInStore,\n          newOpts.publishedBy\n        );\n\n        if (pickedPackage) {\n          return {\n            meta: metaCachedInStore,\n            pickedPackage,\n          };\n        }\n      }\n    }\n\n    try {\n      let meta = await ctx.fetch(\n        spec.name,\n        newOpts?.registry ?? '',\n        newOpts?.authHeaderValue\n      );\n\n      if (ctx.filterMetadata === true) {\n        meta = clearMeta(meta);\n      }\n\n      meta.cachedAt = Date.now();\n      // only save meta to cache, when it is fresh\n      ctx.metaCache.set(spec.name, meta);\n\n      if (newOpts?.dryRun !== true) {\n        // We stringify this meta here to avoid saving any mutations that could happen to the meta object.\n        const stringifiedMeta = JSON.stringify(meta);\n\n        runLimited(pkgMirror, (limit: LimitFunction) => {\n          return limit(async () => {\n            try {\n              await saveMeta(pkgMirror, stringifiedMeta);\n              // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars\n            } catch (_err: any) {\n              // We don't care if this file was not written to the cache\n            }\n          });\n        });\n      }\n      return {\n        meta,\n        pickedPackage: _pickPackageFromMeta(\n          spec,\n          newOpts?.preferredVersionSelectors,\n          meta,\n          newOpts?.publishedBy\n        ),\n      };\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    } catch (err: any) {\n      err.spec = spec;\n\n      const meta = await loadMeta(pkgMirror); // TODO: add test for this usecase\n\n      if (meta == null) {\n        throw err;\n      }\n\n      logger.error(err, err);\n\n      logger.debug({ message: `Using cached meta from ${pkgMirror}` });\n\n      return {\n        meta,\n        pickedPackage: _pickPackageFromMeta(\n          spec,\n          newOpts?.preferredVersionSelectors,\n          meta,\n          newOpts?.publishedBy\n        ),\n      };\n    }\n  });\n}\n\nfunction clearMeta(pkg: PackageMeta): PackageMeta {\n  const versions: PackageMeta['versions'] = {};\n  for (const [version, info] of Object.entries(pkg.versions ?? {})) {\n    // The list taken from https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-version-object\n    // with the addition of 'libc'\n    versions[version] = pick.default(\n      [\n        'name',\n        'version',\n        'bin',\n        'directories',\n        'devDependencies',\n        'optionalDependencies',\n        'dependencies',\n        'peerDependencies',\n        'dist',\n        'engines',\n        'peerDependenciesMeta',\n        'cpu',\n        'os',\n        'libc',\n        'deprecated',\n        'bundleDependencies',\n        'bundledDependencies',\n        'hasInstallScript',\n      ],\n      info\n    );\n  }\n\n  return {\n    name: pkg.name,\n    'dist-tags': pkg['dist-tags'],\n    versions,\n    time: pkg.time,\n    cachedAt: pkg.cachedAt,\n  };\n}\n\nfunction encodePkgName(pkgName: string): string {\n  if (pkgName !== pkgName.toLowerCase()) {\n    return `${pkgName}_${createHexHash(pkgName)}`;\n  }\n\n  return pkgName;\n}\n\nasync function loadMeta(pkgMirror: string): Promise<PackageMeta | null> {\n  try {\n    return await loadJsonFile<PackageMeta>(pkgMirror);\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars\n  } catch (_err: any) {\n    return null;\n  }\n}\n\nconst createdDirs = new Set<string>();\n\nasync function saveMeta(pkgMirror: string, meta: string): Promise<void> {\n  const dir = path.dirname(pkgMirror);\n\n  if (!createdDirs.has(dir)) {\n    await fs.mkdir(dir, { recursive: true });\n    createdDirs.add(dir);\n  }\n\n  const temp = pathTemp(pkgMirror);\n  await gfs.writeFile(temp, meta);\n  await renameOverwrite(temp, pkgMirror);\n}\n\nfunction validatePackageName(pkgName: string): void {\n  if (pkgName.includes('/') && !pkgName.startsWith('@')) {\n    throw new PnpmError(\n      'INVALID_PACKAGE_NAME',\n      `Package name ${pkgName} is invalid, it should have a @scope`\n    );\n  }\n}\n"],
  "mappings": "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",
  "names": ["spec", "limit"]
}
