// Verifies that after dropping a member's dependencies and reinstalling, the
// stale links are pruned from the member `node_modules` so the dropped
// dependencies are no longer resolvable from the member.

function assertMissing(path: string) {
  let exists = true;
  try {
    // lstat (not stat) so a dangling symlink still counts as present.
    Deno.lstatSync(path);
  } catch (err) {
    if (err instanceof Deno.errors.NotFound) {
      exists = false;
    } else {
      throw err;
    }
  }
  if (exists) {
    throw new Error(`expected ${path} to be pruned`);
  }
}

// The dropped npm dependencies and their now-empty scope directory are gone.
assertMissing("package1/node_modules/@denotest/esm-basic");
assertMissing("package1/node_modules/@denotest/bin");
assertMissing("package1/node_modules/@denotest");

// package1 dropped its only bin dependency, so the now-stale `.bin` entry is
// pruned (the `.bin` shim is a plain file on Windows, not a symlink, so this
// exercises the dedicated `.bin` clearing rather than the symlink pruning).
assertMissing("package1/node_modules/.bin/cli-esm");

// The dropped sibling workspace member link is gone.
assertMissing("package2/node_modules/package1");

// but package2 still declares `@denotest/bin`, so its `.bin` entry is kept: the
// `.bin` is rebuilt from the member's current dependencies, not wiped wholesale.
const binStat = Deno.lstatSync("package2/node_modules/.bin/cli-esm");
if (!binStat.isSymlink && !binStat.isFile) {
  throw new Error("expected package2's `.bin/cli-esm` entry to be kept");
}

// but a dependency that is still declared (here package2's devDependency) is
// kept, so pruning only removes the links that became stale.
const stat = Deno.statSync(
  "package2/node_modules/@denotest/cjs-default-export",
);
if (!stat.isDirectory) {
  throw new Error("expected package2's devDependency to be kept");
}

// Pruning a member's `node_modules` must not reach into the workspace root's
// `node_modules`: a still-resolvable package (package2's devDependency) is
// kept there. (If the `is_root` check regressed, the reinstall would treat the
// root as a member with no declared deps and prune it.)
const rootStat = Deno.statSync("node_modules/@denotest/cjs-default-export");
if (!rootStat.isDirectory) {
  throw new Error("expected the workspace root node_modules to be untouched");
}

console.log("pruned");
