Welcome to Chapter 4 of the Stickers Project tutorial!
In the previous chapter, Command Execution Logic, we wrote the code to open the web browser. At the end of that function, instead of simply printing text to the screen, we returned a specific object.
In this chapter, we will explore Standardized Command Output. We will understand why we wrap our results in a specific format and how this keeps our application clean and consistent.
Imagine you run a massive logistics company. You have trucks delivering thousands of packages every day.
If the drivers had to open every box to figure out how to handle it, deliveries would be slow and items would break.
The Solution: You attach a Standardized Manifest (Label) to every box. The driver doesn't look inside; they just read the label:
In our CLI, the "Main System" is the driver. Your command (stickers) creates the package.
console.log. The Main System has no idea if it succeeded, failed, or requires special formatting.LocalCommandResult. The Main System reads the type and handles the formatting automatically.Let's look at the problem we are solving. We want to tell the user that the browser is opening.
If we just used console.log, we would have to decide the text color and spacing inside our command. If we wanted to change the text color of all commands in the future, we would have to edit 100 different files.
By using an object, we delegate the "Styling" to the Main System.
LocalCommandResultThis is the shape (Type) of the object we must return. It acts as our contract.
// types/command.ts (Simplified)
export type LocalCommandResult = {
type: 'text' | 'error'; // The Category
value: string; // The Content
}
Key Concepts:
type: This is the "Category." Is this a normal message? Is it an error? Is it a JSON data object?value: This is the actual data or message you want to convey.
Now, let's look at how we applied this in our stickers.ts file from the previous chapter.
When the browser opens successfully, we wrap our message in a "text" label.
// stickers.ts
// ...
if (success) {
return {
type: 'text',
value: 'Opening sticker page in browserβ¦'
}
}
Explanation:
'text'.If the browser fails to open, we might want to return an error (or text with a different message).
// stickers.ts
// ...
return {
type: 'text',
value: `Failed to open browser. Visit: ${url}`,
}
Note: In a more complex system, we might change type to 'error'. If we did that, the Main System could automatically print the text in Red or add a generic "X" icon, without us writing that logic here.
How does the system process this object? It separates the Data (what you returned) from the Presentation (what the user sees).
Here is the flow of information:
Let's look at a simplified version of the code that runs after your command finishes. This code lives in the core of the CLI framework.
It acts like a switchboard operator, routing different result types to different display functions.
// internal/display-manager.ts (Simplified)
function displayResult(result: LocalCommandResult) {
switch (result.type) {
case 'text':
// Standard formatting
console.log(result.value);
break;
case 'error':
// Error formatting (Red text)
console.error(`\x1b[31mError: ${result.value}\x1b[0m`);
break;
}
}
Why is this powerful?
type: 'error'.display-manager.ts), not in your sticker command.In this chapter, we learned about Standardized Command Output.
console.log calls.LocalCommandResult.{ type, value }, we allow the main system to handle formatting and error states consistently.We have now covered how to register a command, how to load it, how to execute logic, and how to return data. There is one final piece to the puzzle: utilizing the helper tools provided by the system.
In our code, we used a function called openBrowser. Where did that come from? Let's explore the toolbox in the final chapter.
Next Chapter: System Integration Utilities
Generated by Code IQ