fix(scripts): validate the bin name and that its file exists

Copilot review on #1997:

- A string-form `bin` is npm's shorthand for ONE command, named after the
  package, so ignoring `binName` let a typo silently resolve the package's
  only executable while bypassing the documented "declares no such bin"
  failure. Match it against the manifest's unscoped name instead.
- A declared bin whose file is absent (partial install) was returned
  unchecked. `process.execPath <missing>` still spawns and exits 1 with
  empty stdout, which `rawProjectListing` records as "no diagnostic
  captured" — reproducing the bogus every-file-uncovered report this
  helper exists to eliminate. Throw here, where the remedy is actionable.

Also restores `rawProjectListing`'s docblock, which the new `tscEntry`
block had orphaned above itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01387r3MotGk52hrkfjzHFsN
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-16 23:43:24 -04:00
commit 4b143ce043

View file

@ -191,16 +191,6 @@ export function resolveLeafProjects(clientDir, project, seen = new Set()) {
);
}
/**
* Every file ONE project's program resolves, as absolute POSIX paths and with no
* filtering at all — first-party sources, `node_modules` declarations, and the
* out-of-repo `lib.*.d.ts` — plus the config diagnostic if `tsc` exited
* non-zero. The two consumers want different slices of the files, so the slicing
* happens in {@link projectSourceFiles} / {@link projectPackageFiles} rather than
* here; they differ on the `error` too, which is why it is reported rather than
* only warned about. Memoized per (client, project): the same project is listed
* by `resolveLeafProjects` and again by whichever slice the caller asks for.
*/
/**
* The tsc JS entry a client's programs are measured with, resolved from the
* client dir up the node_modules tree exactly as `npx --no-install tsc` walked
@ -229,6 +219,16 @@ export function tscEntry(clientDir) {
return entry;
}
/**
* Every file ONE project's program resolves, as absolute POSIX paths and with no
* filtering at all — first-party sources, `node_modules` declarations, and the
* out-of-repo `lib.*.d.ts` — plus the config diagnostic if `tsc` exited
* non-zero. The two consumers want different slices of the files, so the slicing
* happens in {@link projectSourceFiles} / {@link projectPackageFiles} rather than
* here; they differ on the `error` too, which is why it is reported rather than
* only warned about. Memoized per (client, project): the same project is listed
* by `resolveLeafProjects` and again by whichever slice the caller asks for.
*/
const listingCache = new Map();
export function rawProjectListing(clientDir, project) {
const key = `${clientDir}|${project}`;