๐ŸŽ“ commands/skills/ ยท 03_local_jsx_execution_interface.md

Chapter 3: Local JSX Execution Interface

๐Ÿ“„ commands/skills/03_local_jsx_execution_interface.md

Chapter 3: Local JSX Execution Interface

Welcome back! In the previous chapter, Lazy Module Loading, we learned how to efficiently fetch the code for our skills command only when needed.

We have successfully opened the "book" from the library. Now, we need to read it. Specifically, we are looking at the file skills.tsx.

In this chapter, we will explore the Local JSX Execution Interface. This is the standard way our system runs commands that display a user interface (UI).

The Motivation: The Stage Director

Imagine a theater.

We need a middleman. We need a Stage Director.

In our project, the call function acts as this Stage Director. It is the bridge between the technical command-line runner and the visual React components.

The Use Case: Launching the Menu

Our goal is simple: When the system runs the skills command, we want to display the <SkillsMenu /> component on the screen.

The system looks for a specific function named call inside our file to make this happen.

Step 1: Setting the Stage (Imports)

First, let's look at the top of skills.tsx. We need to bring in our actors (the components) and some rules (types).

// skills.tsx
import * as React from 'react';
// We import the component we want to show
import { SkillsMenu } from '../../components/skills/SkillsMenu.js';
// We import types to make sure we follow the rules
import type { LocalJSXCommandContext } from '../../commands.js';
import type { LocalJSXCommandOnDone } from '../../types/command.js';

Explanation: We are importing React (to build UI), the SkillsMenu (the visual part user sees), and some TypeScript definitions to help us write bug-free code.

Step 2: The Director Enters (The call function)

This is the most important part of this chapter. The system expects a function explicitly named call.

// The system calls this function automatically
export async function call(
  onDone: LocalJSXCommandOnDone, 
  context: LocalJSXCommandContext
): Promise<React.ReactNode> {
  // Logic goes here...
}

Explanation:

Step 3: Handling the Inputs

The call function receives two very important tools (arguments):

  1. onDone: This is the "Close Curtain" button. Since this is a Command Line Interface (CLI), the program must eventually exit. We pass this tool to our component so it knows how to quit.
  2. context: This is the "Script" or "Props." It contains data the command needs, like configuration options or arguments typed by the user.

Step 4: Action! (Returning the UI)

Finally, the director decides what to put on stage. We take the onDone tool and the data from context and hand them to our component.

// Inside the call function:
return (
  <SkillsMenu 
    onExit={onDone} 
    commands={context.options.commands} 
  />
);

Explanation:

Putting it all together

Here is the complete, minimal code for skills.tsx:

import * as React from 'react';
import { SkillsMenu } from '../../components/skills/SkillsMenu.js';
// ... imports for types ...

export async function call(onDone, context) {
  // The Director sets the stage
  return <SkillsMenu onExit={onDone} commands={context.options.commands} />;
}

Under the Hood: The Execution Flow

How does the system actually run this? It doesn't magically know about React. It follows a strict process.

Sequence Diagram

Here is what happens the moment the file is loaded (from Chapter 2).

sequenceDiagram participant Runner as System Runner participant File as skills.tsx (Director) participant UI as <SkillsMenu /> participant User Note over Runner: 1. Looks for "call" function Runner->>File: Run call(onDone, context) File-->>Runner: Returns React Component Runner->>UI: Renders UI to Terminal User->>UI: Selects an item Note over UI: User is finished UI->>Runner: Executes onDone() Runner->>Runner: Exits process
  1. Discovery: The Runner looks for export async function call.
  2. Invocation: It executes that function, injecting the onDone callback and the context object.
  3. Rendering: The function returns a React Node. The Runner takes this node and uses a special library (like Ink) to draw it as text in the terminal.
  4. Completion: When the user is done interacting with the menu, the component calls onDone, signaling the Runner to stop the process.

Internal Implementation Logic

To understand this better, here is a simplified example of the code running your command. You don't write this, but the system uses logic like this:

// Simplified System Runner
async function runCommand(module: any, globalConfig: any) {
  
  // 1. Create the "Curtain Down" function
  const onDone = () => {
    console.log("Exiting command...");
    process.exit(0);
  };

  // 2. Prepare the context (See Chapter 4)
  const context = { options: globalConfig };

  // 3. Run the Director (Your code!)
  const uiElement = await module.call(onDone, context);

  // 4. Render the result to the screen
  render(uiElement);
}

Explanation:

Summary

In this chapter, we learned about the Local JSX Execution Interface.

We saw that we passed context.options.commands to our menu:

commands={context.options.commands}

But wait... where did context come from? How did the system know what options to put inside it? This is a powerful feature called Dependency Injection.

We will explore how data flows into this context in the next chapter.

Next Chapter: Context Dependency Injection


Generated by Code IQ