{"version":3,"file":"unbuilt-imports.d.ts","sourceRoot":"","sources":["../../src/unbuilt-imports.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAKpC,eAAO,MAAM,IAAI,wBAkBhB,CAAA;AAwCD,eAAO,MAAM,IAAI,8DAiChB,CAAA;AAGD,eAAO,MAAM,MAAM,8CAelB,CAAA","sourcesContent":["// this is the thing that supports top-level package.json imports\n// via symlinks, not the tshy.imports which are just config.\nimport { writeFileSync } from 'fs'\nimport { symlink } from 'fs/promises'\nimport { mkdirp } from 'mkdirp'\nimport { dirname, relative, resolve, sep } from 'path'\nimport { getAllConditionalValues } from 'resolve-import/get-all-conditional-values'\nimport { getUniqueConditionSets } from 'resolve-import/get-unique-condition-sets'\nimport { resolveAllLocalImports } from 'resolve-import/resolve-all-local-imports'\nimport { rimraf } from 'rimraf'\nimport { fileURLToPath } from 'url'\nimport * as console from './console.js'\nimport { Package } from './types.js'\n\nconst dirsMade = new Set<string>()\n\n// write out the steps to the save file script\nexport const save = (f: string): boolean => {\n  const links = [...saveSet.entries()]\n  if (!links.length) return false\n  const dirs = new Set<string>(links.map(([dest]) => dirname(dest)))\n  console.debug('save import linker', f)\n  writeFileSync(\n    f,\n    `import { mkdirSync } from 'node:fs'\nimport { symlink } from 'node:fs/promises'\nconst dirs = ${JSON.stringify([...dirs])}\nconst links = [\n${links.map(l => `  ${JSON.stringify(l)},\\n`).join('')}]\nconst e = (er) => { if (er.code !== 'EEXIST') throw er }\nfor (const d of dirs) mkdirSync(d, { recursive: true })\nPromise.all(links.map(([dest, src]) => symlink(src, dest).catch(e)))\n`,\n  )\n  return true\n}\n\nlet targets: undefined | string[] = undefined\n// Get the targets that will have to be linked, because they're not\n// a target in ./src\nconst getTargets = async (imports: Record<string, any>) => {\n  const conds = getAllConditionalValues(imports).filter(\n    c => !c.startsWith('./src/'),\n  )\n  if (!conds.some(c => c.includes('*'))) {\n    // fast path\n    return (targets = conds.filter(c => c.startsWith('./')))\n  }\n  const sets = getUniqueConditionSets(imports)\n  const t = new Set<string>()\n  const pj = resolve('package.json')\n  for (const conditions of sets) {\n    const imps = await resolveAllLocalImports(pj, { conditions })\n    for (const url of Object.values(imps)) {\n      // node builtin\n      if (typeof url === 'string') continue\n      const p = fileURLToPath(url)\n      const rel = relative(process.cwd(), p)\n      // if it's empty, a dep in node_modules, or a built module, skip\n      if (\n        !rel ||\n        rel.startsWith('..' + sep) ||\n        rel.startsWith('src' + sep) ||\n        rel.startsWith('node_modules' + sep)\n      )\n        continue\n      t.add('./' + rel.replace(/\\\\/g, '/'))\n    }\n  }\n  return (targets = [...t])\n}\n\nconst saveSet = new Map<string, string>()\n\n// create symlinks for the package imports in the target dir\nexport const link = async (pkg: Package, dir: string, save = false) => {\n  const { imports } = pkg\n  if (!imports) return\n  if (!targets) targets = await getTargets(imports)\n  if (!targets.length) return\n  console.debug(`link import targets in ${dir}`, targets)\n  const rel = relative(resolve(dir), process.cwd())\n  const lps: Promise<any>[] = []\n  for (const t of targets) {\n    const l = t.replace(/^\\.\\//, '')\n    const df = dirname(l)\n    const dfrel =\n      df === '.' ? '' : (\n        df\n          .split('/')\n          .map(() => '../')\n          .join('')\n      )\n    const dest = dir + '/' + l\n    const src = rel + '/' + dfrel + l\n    if (save) saveSet.set(dest, src)\n    lps.push(\n      mkdirp(dirname(dest))\n        .then(d => {\n          // if we aren't saving, then this is a transient link\n          // save the dirs created so that we can clean them up\n          if (!save && d) dirsMade.add(d)\n          return rimraf(dest)\n        })\n        .then(() => symlink(src, dest)),\n    )\n  }\n  await Promise.all(lps)\n}\n\n// remove symlinks created for package imports in the target dir\nexport const unlink = async (pkg: Package, dir: string) => {\n  const { imports } = pkg\n  if (!imports) return\n  // will always have targets by this point\n  /* c8 ignore start */\n  if (!targets) targets = await getTargets(imports)\n  /* c8 ignore stop */\n  console.debug(`unlink import targets in ${dir}`, targets)\n  const lps: Promise<any>[] = []\n  for (const t of targets) {\n    const dest = resolve(dir, t)\n    lps.push(rimraf(dest))\n  }\n  for (const d of dirsMade) lps.push(rimraf(d))\n  await Promise.all(lps)\n}\n"]}