{
  "version": 3,
  "sources": ["../../../../src/packages/lockfile.verification/linkedPackagesAreUpToDate.ts"],
  "sourcesContent": ["import path from 'node:path';\nimport type {\n  PackageSnapshot,\n  ProjectSnapshot,\n  PackageSnapshots,\n} from '../lockfile.types/index.ts';\nimport { refIsLocalDirectory } from '../lockfile.utils/index.ts';\nimport { safeReadPackageJsonFromDir } from '../read-package-json/index.ts';\nimport { refToRelative } from '../dependency-path/index.ts';\nimport type { WorkspacePackages } from '../resolver-base/index.ts';\nimport {\n  DEPENDENCIES_FIELDS,\n  DEPENDENCIES_OR_PEER_FIELDS,\n  type DependencyManifest,\n  type ProjectManifest,\n} from '../types/index.ts';\nimport pEvery from 'p-every';\nimport semver from 'semver';\nimport getVersionSelectorType from 'version-selector-type';\n\nexport async function linkedPackagesAreUpToDate(\n  {\n    linkWorkspacePackages,\n    manifestsByDir,\n    workspacePackages,\n    lockfilePackages,\n    lockfileDir,\n  }: {\n    linkWorkspacePackages: boolean;\n    manifestsByDir: Record<string, DependencyManifest>;\n    workspacePackages?: WorkspacePackages | undefined;\n    lockfilePackages?: PackageSnapshots | undefined;\n    lockfileDir: string;\n  },\n  project: {\n    dir: string;\n    manifest?: ProjectManifest | undefined;\n    snapshot?: ProjectSnapshot | undefined;\n  }\n): Promise<boolean> {\n  return pEvery.default(\n    DEPENDENCIES_FIELDS,\n    (depField: 'optionalDependencies' | 'dependencies' | 'devDependencies') => {\n      const lockfileDeps = project.snapshot?.[depField];\n      const manifestDeps = project.manifest?.[depField];\n\n      if (\n        typeof lockfileDeps === 'undefined' ||\n        typeof manifestDeps === 'undefined'\n      ) {\n        return true;\n      }\n\n      const depNames = Object.keys(lockfileDeps);\n\n      return pEvery.default(\n        depNames,\n        async (depName: string): Promise<boolean> => {\n          const currentSpec = manifestDeps[depName];\n\n          if (typeof currentSpec === 'undefined') {\n            return true;\n          }\n\n          const lockfileRef = lockfileDeps[depName];\n\n          if (typeof lockfileRef === 'undefined') {\n            return true;\n          }\n\n          const specifier = project.snapshot?.specifiers[depName];\n\n          if (typeof specifier === 'undefined') {\n            return true;\n          }\n\n          if (refIsLocalDirectory(specifier)) {\n            const depPath = refToRelative(lockfileRef, depName);\n            return (\n              depPath != null &&\n              isLocalFileDepUpdated(lockfileDir, lockfilePackages?.[depPath])\n            );\n          }\n\n          const isLinked = lockfileRef.startsWith('link:') === true;\n\n          if (\n            isLinked &&\n            (currentSpec.startsWith('link:') ||\n              currentSpec.startsWith('file:') ||\n              currentSpec.startsWith('workspace:.'))\n          ) {\n            return true;\n          }\n\n          // https://github.com/pnpm/pnpm/issues/6592\n          // if the dependency is linked and the specified version type is tag, we consider it to be up-to-date to skip full resolution.\n          if (isLinked && getVersionSelectorType(currentSpec)?.type === 'tag') {\n            return true;\n          }\n\n          const linkedDir = isLinked\n            ? path.join(project.dir, lockfileRef.slice(5))\n            : workspacePackages?.get(depName)?.get(lockfileRef)?.rootDir;\n\n          if (typeof linkedDir === 'undefined') {\n            return true;\n          }\n\n          if (!linkWorkspacePackages && !currentSpec.startsWith('workspace:')) {\n            // we found a linked dir, but we don't want to use it, because it's not specified as a\n            // workspace:x.x.x dependency\n            return true;\n          }\n\n          const linkedPkg =\n            manifestsByDir[linkedDir] ??\n            (await safeReadPackageJsonFromDir(linkedDir));\n\n          const availableRange = getVersionRange(currentSpec);\n\n          // This should pass the same options to semver as @pnpm/npm-resolver\n          const localPackageSatisfiesRange =\n            availableRange === '*' ||\n            availableRange === '^' ||\n            availableRange === '~' ||\n            (linkedPkg &&\n              semver.satisfies(linkedPkg.version, availableRange, {\n                loose: true,\n              }));\n\n          if (isLinked !== localPackageSatisfiesRange) {\n            return false;\n          }\n\n          return true;\n        }\n      );\n    }\n  );\n}\n\nasync function isLocalFileDepUpdated(\n  lockfileDir: string,\n  pkgSnapshot: PackageSnapshot | undefined\n): Promise<boolean> {\n  if (typeof pkgSnapshot === 'undefined') {\n    return false;\n  }\n\n  const dir =\n    typeof pkgSnapshot.resolution !== 'undefined' &&\n    'directory' in pkgSnapshot.resolution\n      ? pkgSnapshot.resolution.directory\n      : undefined;\n\n  if (typeof dir === 'undefined') {\n    return false;\n  }\n\n  const localDepDir = path.join(lockfileDir, dir);\n\n  const manifest = await safeReadPackageJsonFromDir(localDepDir);\n\n  if (manifest === null) {\n    return false;\n  }\n\n  for (const depField of DEPENDENCIES_OR_PEER_FIELDS) {\n    if (depField === 'devDependencies') {\n      continue;\n    }\n\n    const manifestDeps = manifest[depField] ?? {};\n\n    const lockfileDeps = pkgSnapshot[depField] ?? {};\n\n    // Lock file has more dependencies than the current manifest, e.g. some dependencies are removed.\n    if (\n      Object.keys(lockfileDeps).some((depName: string): boolean => {\n        return typeof manifestDeps[depName] === 'undefined';\n      })\n    ) {\n      return false;\n    }\n\n    for (const depName of Object.keys(manifestDeps)) {\n      // If a dependency does not exist in the lock file, e.g. a new dependency is added to the current manifest.\n      // We need to do full resolution again.\n      if (typeof lockfileDeps[depName] === 'undefined') {\n        return false;\n      }\n      const currentSpec = manifestDeps[depName];\n      // We do not care about the link dependencies of local dependency.\n      if (\n        typeof currentSpec === 'undefined' ||\n        currentSpec.startsWith('file:') === true ||\n        currentSpec.startsWith('link:') === true ||\n        currentSpec.startsWith('workspace:') === true\n      ) {\n        continue;\n      }\n\n      if (\n        semver.satisfies(lockfileDeps[depName], getVersionRange(currentSpec), {\n          loose: true,\n        })\n      ) {\n        continue;\n      }\n\n      return false;\n    }\n  }\n\n  return true;\n}\n\nfunction getVersionRange(spec: string): string {\n  let newSpec = spec;\n\n  if (newSpec.startsWith('workspace:')) {\n    return newSpec.slice(10);\n  }\n\n  if (newSpec.startsWith('npm:')) {\n    newSpec = newSpec.slice(4);\n\n    const index = newSpec.indexOf('@', 1);\n\n    if (index === -1) {\n      return '*';\n    }\n\n    return newSpec.slice(index + 1) || '*';\n  }\n\n  return newSpec;\n}\n"],
  "mappings": "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",
  "names": []
}
