@algolia/coquille
TypeScript icon, indicating that this package has built-in type declarations

0.0.29 • Public • Published

🐚 Coquille

Coquille is React component that renders a terminal on the browser with some built-in features.

Algolia web CLI is built on top of Coquille! See more here.

Features

  • Command parsing (with usage of double quotes " and single quotes ' for values)
  • Suggestions for commands, sub commands, arguments, flag names, flag values (single or comma separated)
  • Terminal shortcuts
    • CTRL+L: clear terminal
    • CTRL+U: erase current line
    • CTRL+A: place cursor to the beginning of the line
  • Automatic errors based on commands structure (wrong flag or argument) is run
  • Click on previous command to copy to clipboard

💻 Installation

To add the library to your project, run

  pnpm/yarn add @algolia/coquille

or

  npm install @algolia/coquille

😌 Quickstart

import Coquille, { Commands } from '@algolia/coquille';

const commands: Commands = {
  ls: {
    shortDesc: 'List mocked files and folders',
    args: { nbArgs: 0 },
    run: () => (
      <ul>
        {['readme.txt', 'index.js', 'coquille.ts'].map((fileName) => (
          <li key={fileName}>{fileName}</li>
        ))}
      </ul>
    ),
  },
};

const MyTerminal = () => (
  <Coquille
    className="my-coquille-class"
    promptPrefix={<span className="my-prefix-class">{'$ >'}</span>}
    commands={commands}
    runOnStart={runOnStart}
  />
);

To define a command with typed flags:

import { Command, FlagValues, RunCommand } from './types';

interface Flags extends FlagValues {
  l: boolean;
}

const run: RunCommand<Flags> = async ({ flags }) => {
  if (flags && flags.l) {
    // ...
  }

  return <ul>...</ul>;
};

const ls: Command<Flags> = {
  shortDesc: 'ls – list directory contents',
  args: { nbArgs: 0 },
  flags: {
    l: {
      type: 'boolean',
      shortDesc:
        'List files in the long format, as described in the The Long Format subsection below',
    },
  },
  run,
};

export default ls as Command;

📖 Documentation

Guide

Props interface

interface CoquilleProps {
  commands: Commands; // commands object defined below
  promptPrefix?: ReactNode; // customizable prompt prefix
  runOnStart?: RunCommand; // command to run on component mount
  onCommandRun?: (rawCommand: string, parsedCommand?: ParsedCommand) => void; // callback run when a command is run (even if the command fails)
}

Commands definition

The shell uses a commands object props to parse, define and run commands in the Terminal:

/**
 * Structure of the commands object that defines
 * commands of the terminal
 */
type Commands = {
  [name: string]: Command;
};

/**
 * Structure of the data that represent a command
 */
type Command<F extends FlagValues = FlagValues> = {
  shortDesc?: string; // Description of the command
  help?: HelpFunction;
  run?: RunCommand<F>;
  args?: {
    nbArgs: number; // Number of arguments needed for the command
    suggestions?: Suggestion[]; // Autocomplete suggestions with short description
  };
  flags?: Flags;
  _?: Commands; // Recursive type to represent sub commands
};

/**
 * Structure of cli autocomplete suggestions.
 * Takes a name and an optional alias and description
 */
type Suggestion = {
  name: string;
  alias?: string;
  description?: string;
};

type FlagType = string | number | boolean;
type FlagValues = {
  [name: string]: FlagType | FlagType[];
};

type Flags = {
  [flagName: string]: Flag;
};

type Flag = {
  shortDesc: string; // Description of the flag
  type: 'string' | 'number' | 'boolean'; // Type of the flag value
  multiple?: boolean; // If multiple values are allowed for the flag
  shorthand?: string; // Shorthand letter of the flag
  suggestions?: Suggestion[]; // Autocomplete suggestions with short description
};

/**
 * Structure of the data that represent the command entered by the user
 */
type ParsedCommand<F extends FlagValues = FlagValues> = {
  command: string[];
  args?: string[];
  flags?: F;
};

/** Function that runs a command
 * @returns a ReactNode that will be displayed as the output of the command
 */
type RunCommand<F extends FlagValues = FlagValues> = (
  command: ParsedCommand<F>,
  shell: {
    input: RefObject<HTMLInputElement>; // ref of the input
    inputValue: string; // input value of the current command
    setInputValue: (value: string) => void; // set input value
    history: string[]; // history of previous commands
  }
) => Promise<ReactNode> | ReactNode;

/** Function to display help about a command
 * @returns a ReactNode that provides help
 */
export type HelpFunction = (args: {
  shortDesc?: string;
  subcommands?: Commands;
  flags?: Flags;
}) => ReactNode;

Helpers

Functions

  • runCommandInTerminal: run the specified command in the terminal programmatically. Useful to create button that runs a command (in a help command output for example).
RunCommandInTerminal = (args: {
  command: string;
  input: React.RefObject<HTMLInputElement>;
  setInputValue: (value: string) => void;
}) => void;
  • dispatchKeyboardEventInTerminal: dispatch the specified keyboard event in the terminal programmatically. Useful to simulate user action (in an interactive demo for example).
DispatchKeyboardEventInTerminal = (args: {
  event: { type: string; eventInitDict?: KeyboardEventInit };
  input: React.RefObject<HTMLInputElement>;
}) => void;

Components

  • <Help />: renders the help standard output of a command.

Example:

<Help
  // Given by the help callback function of the command
  shortDesc={...}
  subcommands={...}
  flags={...}
  // Customized usage, examples and learnMore
  usage="algolia <command> <subcommand> [flags]"
  examples={[
    `$ algolia search MY_INDEX --query "foo"`,
    `$ algolia profile list`,
    `$ algolia indices list`,
  ]}
  learnMore={
    <>
      <p>
        {`Use 'algolia <command> <subcommand> --help' for more information about a command.`}
      </p>
      <p>
        Read the documentation at{" "}
        <Link href="https://algolia.com/doc/tools/cli">
          https://algolia.com/doc/tools/cli
        </Link>
      </p>
    </>
  }
/>

🛟 Support

Found a bug? Open a new issue and help us to improve the code!

Package Sidebar

Install

npm i @algolia/coquille

Weekly Downloads

66

Version

0.0.29

License

ISC

Unpacked Size

370 kB

Total Files

105

Last publish

Collaborators

  • wwalser
  • jkaho
  • mprevell97
  • louishousiaux
  • antoine.gilles
  • eventexperiences_algolia
  • jsok_algolia
  • bhinchley-algolia
  • hugowit
  • alg-admin
  • aymeric.giraudet
  • gavinwade12
  • bhcastle
  • rishi_algolia
  • jasonberry
  • scyganek-algolia
  • drodriguln
  • abodelot
  • leviwhalen
  • sfaiqh
  • valentindotxyz
  • fluf
  • instantsearch-bot
  • taylorcjohnson_algolia
  • pjankowski5312
  • raed-algolia
  • dylantientcheu
  • catalgolia
  • morgan-algolia
  • algabet
  • andy_ds
  • bengreenbank
  • alg-bgastinne
  • daltondickalgolia
  • jcohonner-algolia
  • robertmogos
  • mariaalungu
  • emmanuel.fortin
  • ejaldorau
  • dhaya.b
  • lukyvj
  • marielaure
  • haroenv
  • rayrutjes
  • jerska
  • ronanlevesque
  • samouss
  • therealwebby
  • francoischalifour
  • jonmontane
  • tkrugg
  • seafoox
  • sylvainh
  • clemfromspace
  • lorrissaintgenez
  • broujo
  • e-krebs
  • kombucha
  • sylvain
  • crawler-team
  • amcdaid106
  • devinalgolia
  • jvenezia
  • otomatik
  • sophiem03
  • sarahdayan
  • dcoates
  • maximehuang
  • guitek
  • matthewbond
  • cyril.descossy
  • tatsuro
  • danajeremy
  • mathougui
  • xavdh
  • agdavid
  • rasemotte
  • plnech
  • shortcuts
  • praagyajoshi
  • loicsay
  • svensoldin
  • alphonseb
  • leodau
  • fabienmotte
  • sarahfranc
  • millotp