Get Started

Mustard is a command-line application framework based on the new ES decorator, which aims to provide an OOP-oriented command-line building paradigm based on the type checking capabilities of native TS.

Prerequisites

  • Node.js >= 16.0.0
  • TypeScript >= 5.0.0

Create new project

By default, this command creates a new project with only root command, run with --template=complete to create project with commands.

npm
npx create-mustard-app
yarn
yarn create-mustard-app
pnpm
pnpx create-mustard-app
cd mustard-app
npm run dev

Start manually

npm
npm i mustard-cli
npm i typescript ts-node -D
yarn
yarn add mustard-cli
yarn add typescript ts-node -D
pnpm
pnpm i mustard-cli
pnpm i typescript ts-node -D

You can use any executor besides ts-node, just like esno. Tutorial from this documentation is based on ts-node + nodemon.

Create minimial tsconfig.json as following:

{
  "ts-node": {
    "swc": false,
    "pretty": true,
    "transpileOnly": true,
  },
  "compilerOptions": {
    "target": "ES6",
    "module": "ES2022",
    "moduleResolution": "node",
    "strict": true,
    "declaration": false,
    "baseUrl": ".",
  },
  "include": ["src"],
  "exclude": []
}

Add essential parts to package.json:

{
  "name": "awesome-mustard-app",
  "version": "0.0.1",
  "type": "module",
  "main": "index.js",
  "bin": {
    "awesome-mustard-app": "index.js"
  },
  "files": [
    "dist",
    "index.js"
  ],
  "scripts": {
    "dev": "nodemon src/index.mts",
    "start": "npm run build && nodemon index.js",
    "build": "tsc",
  },
  "nodemonConfig": {
    "delay": 500,
    "execMap": {
      "js": "node --experimental-specifier-resolution=node",
      "ts": "NODE_OPTIONS='--experimental-specifier-resolution=node' ts-node-esm",
      "mts": "NODE_OPTIONS='--experimental-specifier-resolution=node' ts-node-esm"
    },
    "ext": "ts,mts,js,mjs,json",
    "ignore": [
      "**/test/**",
      "**/docs/**",
      "node_modules"
    ],
    "verbose": true,
    "watch": [
      "*.ts",
      "*.mts",
      "*.js",
      "*.mjs"
    ]
  },
  "dependencies": {
    "mustard-cli": "latest"
  },
  "devDependencies": {
    "@types/node": "^18.11.7",
    "nodemon": "^2.0.20",
    "ts-node": "^10.9.1",
    "typescript": "^5.0.0"
  }
}
  • By default Mustard only provides ESM-based modern development workflow, so we need --experimental-specifier-resolution=node.

Create your first root command in index.mts:

import { MustardFactory } from "mustard-cli";
import { RootCommand, App, Input } from "mustard-cli/decorator";
import type { CommandStruct, MustardApp } from "mustard-cli/cli";

@RootCommand()
class RootCommandHandle implements CommandStruct {

  @Input()
  public name: string = "Harold";

  public run(): void {
    console.log(`Hello, ${this.name}!`);
  }
}

@App({
  name: "mm",
  commands: [RootCommandHandle],
})
class Project implements MustardApp {
  onError(error: Error): void {
    console.log(error);
  }
}

MustardFactory.init(Project).start();
$ nodemon index.mts
Hello, Harold!

$ nodemon index.mts Ekko
Hello, Ekko!