# Create controller

## Content Table

* [Create Controller](#create-controller)
  * [Content Table](#content-table)
  * [What a controller should and what it shouldn't to do](#what-a-controller-should-and-what-it-shouldnt-to-do)
  * [How to implement a Controller](#how-to-implement-a-controller)
  * [Controller API Reference](#controller-api-reference)

Currently all the controllers must be implemented inside of the `everdev` package.

To create a new controller:

* Clone `git@github.com:tonlabs/everdev.git`.
* Create and checkout branch for the new controller.
* Create a folder under `src/controllers`.
* Implement the controller code.
* Include the new controller in file `src/controllers/index.js`.
* Create pull request.

## What a controller should and what it shouldn't to do

Controller should:

* Expose functionality to the user as a list of commands.
* Install the required tool components on demand (on first usage).
* Start and stop the tool components that acts like a demons.
* Define three commands to control the tool version:
  * `version` to show the currently installed tool version;
  * `update` to update the tool to the latest available version;
  * `use` to select the specified tool version as the current version.

Controller shouldn't:

* Implement tool functionality itself. Controller is a connector between the user and the existing development tool.
* Implement user interaction itself. All user interaction must be implemented exactly in the terms of everdev extensibility.

## How to implement a Controller

Create a folder for a new controller:

```shell
mkdir src/controllers/foo
cd src/controllers/foo
```

Create `index.ts` with the controller's definition:

```ts
import { ToolController } from "../../core";
import { versionCommand } from "./version";
import { updateCommand } from "./update";
import { runCommand } from "./run";

export const Foo: ToolController = {
    name: "foo",
    title: "Foo Tool",
    commands: [
        versionCommand,
        updateCommand,
        runCommand,
    ],
};
```

Create `installer.ts` to implement all the code related to the tool installation:

```ts
import path from "path";
import fs from "fs";
import { Terminal, everdevHome } from "../../core";

function fooHome() {
    return path.resolve(everdevHome(), "foo");
}

async function ensureInstalled(terminal: Terminal) {
}

export async function getVersion(): Promise<string> {
    return "1.0.0";
}

export async function updateVersion(terminal: Terminal) {
    if (fs.existsSync(fooHome())) {
        fs.rmdirSync(fooHome(), { recursive: true });
    }
    ensureInstalled(terminal);
}

export async function runFoo(terminal: Terminal, workDir: string, args: string[]): Promise<void> {
    ensureInstalled(terminal);
    terminal.log("Foo succeeded");
};
```

Create `version.ts` command handler:

```ts
import { getVersion } from "./installer";
import { Command, Terminal } from "../../core";

export const versionCommand: Command = {
    name: "version",
    title: "Show Foo Version",
    async run(terminal: Terminal, _args: {}): Promise<void> {
        terminal.log(await getVersion());
    },
};
```

Create `update.ts` command handler:

```ts
import { updateVersion } from "./installer";
import { Command, Terminal } from "../../core";

export const versionCommand: Command = {
    name: "update",
    title: "Update Foo Version",
    async run(terminal: Terminal, _args: {}): Promise<void> {
        await updateVersion(terminal);
    },
};
```

Create `run.ts` command handler:

```ts
import { runFoo } from "./installer";
import { Command, Terminal } from "../../core";

export const runCommand: Command = {
    name: "run",
    title: "Run Foo",
    async run(terminal: Terminal, args: {}): Promise<void> {
        await runFoo(terminal, args);
    },
};
```

## Controller API Reference

You can find API reference in form of TSDoc in `src/core/index.ts`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.everos.dev/everdev/guides/creating-controller.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
