Add --mission CLI Flag And GET /mission HTTP Endpoint To Expose Repository Mission Statement

by ADMIN 93 views

Overview

In this article, we will explore the implementation of a new "mission" feature that allows users to view the repository's mission statement via both the CLI and the HTTP server. This feature will be achieved by adding a --mission flag to the CLI and a GET /mission endpoint in the persistent HTTP server.

Changes to Apply

CLI Handler

To implement the --mission flag in the CLI handler, we need to make the following changes:

  • Create a new function processMission(args) similar to processVersion:
    • Detect the --mission flag.
    • Read the MISSION.md file from the repository root using fs.readFileSync.
    • On success, output a JSON object: { mission: <file content as string> }.
    • On failure, call logError("Mission CLI failed", error) and return HTTP-style exit.
  • In main(args), call await processMission(args) immediately after version and before default case, and return.

Here is the updated code for the CLI handler:

// sandbox/source/main.js
const fs = require('fs');
const logError = require('./lib/logError');

async function processMission(args) {
    const missionFlag = args.includes('--mission');
    if (!missionFlag) return;

    try {
        const missionContent = fs.readFileSync('MISSION.md', 'utf8');
        console.log(JSON.stringify({ mission: missionContent }));
    } catch (error) {
        logError("Mission CLI failed", error);
        process.exit(1);
    }
}

async function main(args) {
    // ... existing code ...

    await processMission(args);

    // ... existing code ...
}

HTTP Server Endpoint

To implement the GET /mission endpoint in the HTTP server, we need to make the following changes:

  • In the existing processServe(args) function, add a GET /mission route:
    • On request, read MISSION.md from the project root.
    • Respond with status 200 and JSON payload { mission: <string> }.
    • Increment globalThis.callCount and handle errors by returning HTTP 500 with { error, message } using logError.

Here is the updated code for the HTTP server endpoint:

// src/lib/main.js
const fs = require('fs');
const logError = require('./lib/logError');

async function processServe(args) {
    // ... existing code ...

    app.get('/mission', async (req, res) => {
        try {
            const missionContent = fs.readFileSync('MISSION.md', 'utf8');
            res.status(200).json({ mission: missionContent });
            globalThis.callCount++;
        } catch (error) {
            logError("Mission HTTP failed", error);
            res.status(500).json({ error, message: "Internal Server Error" });
        }
    });

    // ... existing code ...
}

Tests

To ensure the correctness of the implementation, we need to write tests for both the CLI and HTTP server endpoints.

CLI Tests

Here are the updated tests for the CLI:

// sandbox/tests/main.test.js
const = require('../source/main');

describe('CLI', () => {
    it('should log mission statement JSON', async () => {
        const args = ['--mission'];
        await main(args);
        expect(console.log).toHaveBeenCalledTimes(1);
        expect(console.log).toHaveBeenCalledWith(JSON.stringify({ mission: 'Mission statement' }));
    });

    it('should log error on mission statement read failure', async () => {
        const fsReadFileSyncMock = jest.spyOn(fs, 'readFileSync').mockImplementationOnce(() => {
            throw new Error('Mocked error');
        });
        const args = ['--mission'];
        await main(args);
        expect(console.error).toHaveBeenCalledTimes(1);
        expect(console.error).toHaveBeenCalledWith('Mission CLI failed: Mocked error');
        fsReadFileSyncMock.mockRestore();
    });
});

HTTP Tests

Here are the updated tests for the HTTP server:

// tests/unit/main.test.js
const fetch = require('node-fetch');
const fs = require('fs');
const logError = require('../lib/logError');

describe('HTTP', () => {
    it('should return mission statement JSON', async () => {
        const fsReadFileSyncMock = jest.spyOn(fs, 'readFileSync').mockImplementationOnce(() => 'Mission statement');
        const port = await startServer();
        const response = await fetch(`http://localhost:${port}/mission`);
        expect(response.status).toBe(200);
        expect(await response.json()).toEqual({ mission: 'Mission statement' });
        fsReadFileSyncMock.mockRestore();
    });

    it('should return error on mission statement read failure', async () => {
        const fsReadFileSyncMock = jest.spyOn(fs, 'readFileSync').mockImplementationOnce(() => {
            throw new Error('Mocked error');
        });
        const port = await startServer();
        const response = await fetch(`http://localhost:${port}/mission`);
        expect(response.status).toBe(500);
        expect(await response.json()).toEqual({ error: 'Mocked error', message: 'Internal Server Error' });
        fsReadFileSyncMock.mockRestore();
    });
});

Documentation

To ensure that the documentation is up-to-date, we need to update the CLI usage section and add HTTP documentation.

Here is the updated documentation:

# CLI Usage

*   `--mission`: Print the mission statement JSON.

# HTTP Endpoints

*   `GET /mission`: Return the mission statement JSON.

Dependencies

No new runtime dependencies are required for this feature.

Verification & Acceptance

To verify the correctness of the implementation, we need to run the tests and ensure that all existing and new tests pass.

Here are the steps to verify the implementation:

  1. Run npm test to ensure that all tests pass.
  2. Run node sandbox/source/main.js --mission to ensure that the mission statement JSON is printed.
  3. Run node sandbox/source/main.js --serve and curl http://localhost:3000/mission to ensure that the mission statement JSON is returned and the metrics are incremented.
  4. Verify that the README updates correctly describe the flag and endpoint with examples.

Q: What is the purpose of adding a --mission flag to the CLI?

A: The purpose of adding a --mission flag to the CLI is to allow users to view the repository's mission statement via the command line. This feature provides users with easy access to the mission statement, making it easier to understand the purpose and goals of the repository.

Q: How does the --mission flag work?

A: The --mission flag works by detecting the presence of the flag in the command line arguments. If the flag is present, the CLI handler reads the MISSION.md file from the repository root and outputs the mission statement as a JSON object.

Q: What is the purpose of the GET /mission endpoint in the HTTP server?

A: The purpose of the GET /mission endpoint in the HTTP server is to provide users with a way to view the repository's mission statement via a web interface. This endpoint allows users to access the mission statement by making a GET request to the /mission endpoint.

Q: How does the GET /mission endpoint work?

A: The GET /mission endpoint works by reading the MISSION.md file from the repository root and returning the mission statement as a JSON object with a status code of 200. If an error occurs while reading the file, the endpoint returns a status code of 500 with an error message.

Q: What are the benefits of implementing the --mission flag and GET /mission endpoint?

A: The benefits of implementing the --mission flag and GET /mission endpoint include:

  • Improved user experience: By providing users with easy access to the mission statement, we can improve their overall experience with the repository.
  • Increased transparency: By making the mission statement easily accessible, we can increase transparency and accountability within the repository.
  • Simplified maintenance: By implementing a single endpoint for the mission statement, we can simplify maintenance and reduce the risk of errors.

Q: How do I implement the --mission flag and GET /mission endpoint in my own repository?

A: To implement the --mission flag and GET /mission endpoint in your own repository, follow these steps:

  1. Create a new file called MISSION.md in the root of your repository and add the mission statement to it.
  2. Update the CLI handler to detect the --mission flag and read the MISSION.md file.
  3. Update the HTTP server to implement the GET /mission endpoint and return the mission statement as a JSON object.
  4. Test the implementation to ensure that it works correctly.

Q: What are some common issues that may arise when implementing the --mission flag and GET /mission endpoint?

A: Some common issues that may arise when implementing the --mission flag and GET /mission endpoint include:

  • File not found errors: If the MISSION.md file is not found, the implementation will fail.
  • File read errors If there is an error reading the MISSION.md file, the implementation will fail.
  • Endpoint not implemented correctly: If the GET /mission endpoint is not implemented correctly, the implementation will fail.

Q: How do I troubleshoot issues with the --mission flag and GET /mission endpoint?

A: To troubleshoot issues with the --mission flag and GET /mission endpoint, follow these steps:

  1. Check the file path: Ensure that the file path to the MISSION.md file is correct.
  2. Check the file contents: Ensure that the MISSION.md file contains the correct mission statement.
  3. Check the endpoint implementation: Ensure that the GET /mission endpoint is implemented correctly.
  4. Test the implementation: Test the implementation to ensure that it works correctly.