The capstone turns the earlier pieces into a small offline Node tool. It reads JSON Lines: each nonblank physical line contains one JSON record. The tool validates every record, selects a mode, aggregates by service and emits one deterministic JSON report. It uses real Node command-line and stream APIs, with no network calls or external packages.
A useful command-line interface exposes three independent results: an exit status, stdout for successful data and stderr for diagnostics. The graded runCLI function returns all three explicitly. A thin wrapper reads arguments and stdin, writes the returned streams, and assigns process.exitCode. Keeping that wrapper small makes application behavior easy to test without terminating the test process.
function run(args, input) {
if (args.length) return {code: 2, stdout: "", stderr: "usage\n"};
return {code: 0, stdout: JSON.stringify({characters: input.length}) + "\n", stderr: ""};
}
const result = run([], "jobs");
process.stdout.write(result.stdout);
process.exitCode = result.code;Validate arguments first. Help and invalid usage should have stable results even when stdin contains malformed text. Accepting exactly one spelling of each supported mode keeps ambiguous combinations out of the interface. The supplied wrapper uses process.argv.slice(2) because Node and the script path occupy the first two entries.
Physical line numbers matter when reporting invalid input. Splitting the input preserves blank lines; skipping their records does not remove their positions. The first nonblank malformed record should identify its original one-based line number. Treat both JSON syntax errors and application schema violations as invalid records at this outer boundary.
The report is atomic: do not print a row while validation is still in progress. A later invalid line must return empty stdout. Accumulating results in local memory and serializing only at the end makes that guarantee straightforward for these bounded fixtures. A large streaming application would need a separate resource and output protocol.
Filtering happens after validation. Under --failed, a malformed record claiming to be successful is still invalid input. Otherwise an option would accidentally become a validation bypass. Group selected records with Map so arbitrary service names remain data, and sort the fresh report rows using the specified string comparator. Count all selected records; increment failed only for a failed state.
Test the complete interface: empty input, blank lines, CRLF, repeated services, a zero duration, a negative duration, a bad argument and an error after a valid record. Verify the exact newline on successful JSON output and the absence of partial stdout on failure. Run the reference file directly with Node to see the same pure behavior applied to actual process streams.
Completing this tool establishes local JavaScript transformation and CLI foundations. A useful next route is TypeScript, then HTTP clients, then a remote API CLI such as a Pokedex. HTTP services add routing, SQL, framework tooling and deployment requirements; this introductory course does not establish all of those prerequisites.