4.2 KiB
suaveplan-hash-password bin entry
(no submodules)
Purpose
This file is the platform-runtime entry for the suaveplan-hash-password
binary shipped by @suaveplan/crypto-bin. It is intentionally a minimal
shim: it constructs an HashPasswordCliEnv adapter from process.stdout
and process.stderr, then delegates to the testable main() function in
../hash-password/hash-password.ts. All argument parsing, algorithm
dispatch, and exit-code logic live in that pure core so they can be unit
tested by direct invocation rather than by spawning a subprocess.
The shim exists so the package can publish a Node-style bin entry under
./dist/bin/hash-password.js (with the #!/usr/bin/env node shebang
preserved by Vite) without coupling the testable core to process.*
globals. Anything that touches process.argv / process.exit /
process.stdout is confined to this module.
Features
- Forwards
process.argv.slice(2)intomain()and exits with the returned numeric code. - Wires
process.stdout.write/process.stderr.writeinto theHashPasswordCliEnvadapter — the core never referencesprocessdirectly. - Auto-exec guard: only runs
main()when invoked as the top-level module (process.argv[1]ends withhash-password.js). Importing this module from a test or another script does not trigger an exit. - Coverage-excluded by design — this module is exercised end-to-end via
the bin install path; the logic it wraps is fully covered by
../hash-password/hash-password.test.ts. - Shebang line emitted verbatim into the dist bundle so the file is
directly executable once symlinked by
bun install/npm install.
Usage: Basic Example
# Once installed, the bin is on PATH via the package.json `bin` map
$ suaveplan-hash-password --password "correct horse battery staple"
$argon2id$v=19$m=65536,t=3,p=1$<salt>$<hash>
$ echo $?
0
Usage: Advanced Example
# Pipe-friendly verify (exit 0 = match, 1 = mismatch, 3+ = error)
$ STORED='$argon2id$v=19$m=65536,t=3,p=1$<salt>$<hash>'
$ if suaveplan-hash-password --password "$PW" --verify "$STORED"; then
> echo "login ok"
> else
> case $? in
> 1) echo "wrong password" ;;
> 3) echo "stored hash has unrecognised algorithm" ;;
> 4) echo "stored hash is corrupt" ;;
> *) echo "argument error" ;;
> esac
> fi
For programmatic invocation that does not spawn a process, import the testable core directly instead of this shim:
import { main } from "@suaveplan/crypto-bin";
const code = main(["--password", "pw"], {
write: (s) => process.stdout.write(s),
writeError: (s) => process.stderr.write(s),
});
API Reference
This module has no public exports — it is a side-effect entry point. Behaviour:
- On import, registers the auto-exec guard and (if invoked as the
top-level script) calls
main(argv, env)and exits with its return value. argv:process.argv.slice(2)— same shapemain()accepts.env.write(s): forwardsstoprocess.stdout.writesynchronously.env.writeError(s): forwardsstoprocess.stderr.writesynchronously.
For the contract of main() itself (exit codes, accepted flags, error
classes) see ../hash-password/hash-password.md.
Implementation Notes
The auto-exec guard checks process.argv[1]?.endsWith("hash-password.js")
rather than import.meta.url === ... so the same module survives Vite's
ES-module bundling without ESM-vs-CJS surprises in older Node hosts. The
guard string matches the bundled filename (hash-password.js) deliberately
— the source is .ts and is never executed directly in production.
/* istanbul ignore */ markers wrap the guard and the process.exit
call because the test suite invokes main() directly with a captured env
adapter (see ../hash-password/hash-password.test.ts). Spawning a
subprocess to cover this two-line wrapper would add filesystem and Node
runtime coupling to the test suite without exercising any logic that is
not already covered. The vitest.config.ts coverage exclude list
documents this decision in a sibling comment so future readers do not
mistake the exclusion for an oversight.