first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
# `suaveplan-hash-password` bin entry
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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)` into `main()` and exits with the
returned numeric code.
- Wires `process.stdout.write` / `process.stderr.write` into the
`HashPasswordCliEnv` adapter — the core never references `process`
directly.
- Auto-exec guard: only runs `main()` when invoked as the top-level
module (`process.argv[1]` ends with `hash-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
```bash
# 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
```bash
# 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:
```ts
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 shape `main()` accepts.
- `env.write(s)`: forwards `s` to `process.stdout.write` synchronously.
- `env.writeError(s)`: forwards `s` to `process.stderr.write`
synchronously.
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.