Capstone: todo CLI
The spec
The todo CLI manages one list: add items, mark them done, remove them, and print what is left. All state lives in a single JSON file next to the script.
Keep the scope tight on purpose: four commands and one file store. A small surface leaves room to finish parsing, storage, and tests in one sitting.
type Todo = {
id: number;
title: string;
done: boolean;
};
Parse argv
Node exposes raw arguments in process.argv, with the first two entries reserved for the binary and the script path. Slice from index two to read only what the user typed.
Map the first word to a command and fall back to list when nothing is given. Unknown words print usage, so the tool teaches itself on every mistake.
function parseArgs(argv: Array<string>): string {
const head: string | undefined = argv[0];
if (head === undefined) {
return "list";
}
return head;
}
const action: string = parseArgs(process.argv.slice(2));
console.log(action);
JSON file store
The store loads the JSON file into an array of todos and writes the whole array back after each change. Full file rewrites stay simple and safe at this size.
Read with readFileSync and parse into unknown before guarding, then stringify on save. Sync calls keep the CLI code linear because the process exits right after.
// Todo from above
import { readFileSync, writeFileSync } from "node:fs";
function loadTodos(path: string): Array<Todo> {
const raw: string = readFileSync(path, "utf8");
return JSON.parse(raw) as Array<Todo>;
}
function saveTodos(path: string, todos: Array<Todo>): void {
writeFileSync(path, JSON.stringify(todos));
}
Assert tests for the store
Test the argument parser and the store with the built in assert module. Each strictEqual call pins one behavior, and any failure throws with a clear diff.
Runtime background lives in the JavaScript section, which covers the event loop and modules the CLI relies on. Run the file with node and watch every assertion pass before wiring the real commands.
// parseArgs from above
import assert from "node:assert";
assert.strictEqual(parseArgs([]), "list");
assert.strictEqual(parseArgs(["add"]), "add");
console.log("store tests pass");
node todo.js list
1. Buy milk
Next: Capstone: JSON API
Article author: Arthur Isaev