{
  "version": 3,
  "sources": ["../../../../src/packages/store-path/index.ts"],
  "sourcesContent": ["import { promises as fs } from 'node:fs';\nimport { STORE_VERSION } from '../constants/index.ts';\nimport { PnpmError } from '../error/index.ts';\nimport rimraf from '@zkochan/rimraf';\nimport canLink from 'can-link';\nimport os from 'node:os';\nimport path from 'node:path';\nimport pathAbsolute from 'path-absolute';\nimport pathTemp from 'path-temp';\nimport rootLinkTarget from 'root-link-target';\nimport touch from 'touch';\n\nexport function getStorePath({\n  pkgRoot,\n  storePath,\n  pnpmHomeDir,\n}: {\n  pkgRoot: string;\n  storePath?: string | undefined;\n  pnpmHomeDir?: string | undefined;\n}): string | Promise<string> {\n  if (typeof storePath === 'undefined') {\n    if (typeof pnpmHomeDir === 'undefined') {\n      throw new PnpmError(\n        'NO_PNPM_HOME_DIR',\n        'The pnpm home directory is unknown. Cannot calculate the store directory location.'\n      );\n    }\n\n    return storePathRelativeToHome(pkgRoot, 'store', pnpmHomeDir);\n  }\n\n  if (isHomepath(storePath)) {\n    const homedir = getHomedir();\n\n    return storePathRelativeToHome(pkgRoot, storePath.substring(2), homedir);\n  }\n\n  const storeBasePath = pathAbsolute(storePath, pkgRoot);\n\n  if (storeBasePath.endsWith(`${path.sep}${STORE_VERSION}`)) {\n    return storeBasePath;\n  }\n\n  return path.join(storeBasePath, STORE_VERSION);\n}\n\nasync function storePathRelativeToHome(\n  pkgRoot: string,\n  relStore: string,\n  homedir: string\n): Promise<string> {\n  const tempFile = pathTemp(pkgRoot);\n  if (path.parse(pkgRoot).root !== pkgRoot) {\n    await fs.mkdir(path.dirname(tempFile), { recursive: true });\n  }\n\n  await touch(tempFile);\n\n  const storeInHomeDir = path.join(homedir, relStore, STORE_VERSION);\n\n  if (await canLinkToSubdir(tempFile, homedir)) {\n    await fs.unlink(tempFile);\n\n    // If the project is on the drive on which the OS home directory\n    // then the store is placed in the home directory\n    return storeInHomeDir;\n  }\n\n  try {\n    let mountpoint = await rootLinkTarget(tempFile);\n\n    // Usually, it is disallowed to write files into the drive's root.\n    // So we create an empty directory and try to link there.\n    // The store will be a directory anyway.\n    const mountpointParent = path.join(mountpoint, '..');\n\n    if (\n      !dirsAreEqual(mountpointParent, mountpoint) &&\n      (await canLinkToSubdir(tempFile, mountpointParent))\n    ) {\n      mountpoint = mountpointParent;\n    }\n\n    // If linking works only in the project folder\n    // then prefer to place the store inside the homedir\n    if (dirsAreEqual(pkgRoot, mountpoint)) {\n      return storeInHomeDir;\n    }\n\n    return path.join(mountpoint, '.pnpm-store', STORE_VERSION);\n  } catch {\n    // this is an unlikely situation but if there is no way to find\n    // a linkable place on the disk, create the store in homedir\n    return storeInHomeDir;\n  } finally {\n    await fs.unlink(tempFile);\n  }\n}\n\nasync function canLinkToSubdir(\n  fileToLink: string,\n  dir: string\n): Promise<boolean> {\n  const tmpDir = pathTemp(dir);\n\n  try {\n    await fs.mkdir(tmpDir, { recursive: true });\n\n    return await canLink(fileToLink, pathTemp(tmpDir));\n  } catch {\n    return false;\n  } finally {\n    await safeRmdir(tmpDir);\n  }\n}\n\nasync function safeRmdir(dir: string): Promise<void> {\n  try {\n    // We cannot use just fs.rmdir here because can-link\n    // sometimes might not remove the temporary file in time\n    // and fs.rmdir can only remove an empty directory.\n    await rimraf(dir);\n  } catch {\n    // ignore\n  }\n}\n\nfunction dirsAreEqual(dir1: string, dir2: string): boolean {\n  return path.relative(dir1, dir2) === '.';\n}\n\nfunction getHomedir(): string {\n  const home = os.homedir();\n\n  if (!home) {\n    throw new Error('Could not find the homedir');\n  }\n\n  return home;\n}\n\nfunction isHomepath(filepath: string): boolean {\n  return filepath.indexOf('~/') === 0 || filepath.indexOf('~\\\\') === 0;\n}\n"],
  "mappings": "AAAA,SAAS,YAAY,UAAU;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAC1B,OAAO,YAAY;AACnB,OAAO,aAAa;AACpB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,kBAAkB;AACzB,OAAO,cAAc;AACrB,OAAO,oBAAoB;AAC3B,OAAO,WAAW;AAEX,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAI6B;AAC3B,MAAI,OAAO,cAAc,aAAa;AACpC,QAAI,OAAO,gBAAgB,aAAa;AACtC,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO,wBAAwB,SAAS,SAAS,WAAW;AAAA,EAC9D;AAEA,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,UAAU,WAAW;AAE3B,WAAO,wBAAwB,SAAS,UAAU,UAAU,CAAC,GAAG,OAAO;AAAA,EACzE;AAEA,QAAM,gBAAgB,aAAa,WAAW,OAAO;AAErD,MAAI,cAAc,SAAS,GAAG,KAAK,GAAG,GAAG,aAAa,EAAE,GAAG;AACzD,WAAO;AAAA,EACT;AAEA,SAAO,KAAK,KAAK,eAAe,aAAa;AAC/C;AAEA,eAAe,wBACb,SACA,UACA,SACiB;AACjB,QAAM,WAAW,SAAS,OAAO;AACjC,MAAI,KAAK,MAAM,OAAO,EAAE,SAAS,SAAS;AACxC,UAAM,GAAG,MAAM,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,EAC5D;AAEA,QAAM,MAAM,QAAQ;AAEpB,QAAM,iBAAiB,KAAK,KAAK,SAAS,UAAU,aAAa;AAEjE,MAAI,MAAM,gBAAgB,UAAU,OAAO,GAAG;AAC5C,UAAM,GAAG,OAAO,QAAQ;AAIxB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,QAAI,aAAa,MAAM,eAAe,QAAQ;AAK9C,UAAM,mBAAmB,KAAK,KAAK,YAAY,IAAI;AAEnD,QACE,CAAC,aAAa,kBAAkB,UAAU,KACzC,MAAM,gBAAgB,UAAU,gBAAgB,GACjD;AACA,mBAAa;AAAA,IACf;AAIA,QAAI,aAAa,SAAS,UAAU,GAAG;AACrC,aAAO;AAAA,IACT;AAEA,WAAO,KAAK,KAAK,YAAY,eAAe,aAAa;AAAA,EAC3D,QAAQ;AAGN,WAAO;AAAA,EACT,UAAE;AACA,UAAM,GAAG,OAAO,QAAQ;AAAA,EAC1B;AACF;AAEA,eAAe,gBACb,YACA,KACkB;AAClB,QAAM,SAAS,SAAS,GAAG;AAE3B,MAAI;AACF,UAAM,GAAG,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AAE1C,WAAO,MAAM,QAAQ,YAAY,SAAS,MAAM,CAAC;AAAA,EACnD,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,UAAM,UAAU,MAAM;AAAA,EACxB;AACF;AAEA,eAAe,UAAU,KAA4B;AACnD,MAAI;AAIF,UAAM,OAAO,GAAG;AAAA,EAClB,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,aAAa,MAAc,MAAuB;AACzD,SAAO,KAAK,SAAS,MAAM,IAAI,MAAM;AACvC;AAEA,SAAS,aAAqB;AAC5B,QAAM,OAAO,GAAG,QAAQ;AAExB,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AAEA,SAAO;AACT;AAEA,SAAS,WAAW,UAA2B;AAC7C,SAAO,SAAS,QAAQ,IAAI,MAAM,KAAK,SAAS,QAAQ,KAAK,MAAM;AACrE;",
  "names": []
}
