Skip to content

Commit

Permalink
docs: add usage section
Browse files Browse the repository at this point in the history
  • Loading branch information
Barbapapazes committed Sep 12, 2023
1 parent f4c4447 commit 26a44f2
Showing 1 changed file with 155 additions and 10 deletions.
165 changes: 155 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,39 @@

🚧 This project is under heavy development. More features are coming soon!

## Usage
## Install

Install package:

```sh
# npm
npm install citty
```

# yarn
```sh
yarn add citty
```

# pnpm
```sh
pnpm install citty
```

Import:
## Usage

### Import Package

```js
// ESM
import { defineCommand, runMain } from "citty";
```

```js
// CommonJS
const { defineCommand, runMain } = require("citty");
```

Define main command to run:
### Main Command

```ts
```js
import { defineCommand, runMain } from "citty";

const main = defineCommand({
Expand All @@ -64,27 +69,167 @@ const main = defineCommand({
description: "Use friendly greeting",
},
},
run({ args }) {
run({ args }) { // Command can be async
console.log(`${args.friendly ? "Hi" : "Greetings"} ${args.name}!`);
},
});

runMain(main);
```

### Sub Commands

You can define sub commands and attach them to main command to create a nested command structure. This is recursive so you can attach sub commands to sub commands, etc.

```js
import { defineCommand, runMain } from "citty";

// First, you define a new command
const sub = defineCommand({
meta: {
name: "sub",
description: "Sub command",
},
args: { // Sub commands can have their own arguments like any other command
name: {
type: "positional",
description: "Your name",
required: true,
},
},
run({ args }) { // Command can be async
console.log(`Hello ${args.name}!`);
},
});

// Then, you define a main command and attach sub command to it
const main = defineCommand({
meta: {
name: "hello",
version: "1.0.0",
description: "My Awesome CLI App",
},
commands: {
sub, // Attach sub command to main command
},
});

runMain(main);
```

### Hooks

`citty` supports a `setup` and `cleanup` functions that are called before and after command execution. This is useful for setting up and cleaning up resources.

Only the `setup` and `cleanup` functions from the command called are executed. For example, if you run `hello sub`, only the `setup` and `cleanup` functions from `sub` command are executed and not the ones from `hello` command.

```js
import { defineCommand, runMain } from "citty";

const main = defineCommand({
meta: {
name: "hello",
version: "1.0.0",
description: "My Awesome CLI App",
},
setup() { // Setup function is called before command execution or before any sub command execution
console.log("Setting up...");
},
cleanup() { // Cleanup function is called after command execution or after any sub command execution
console.log("Cleaning up...");
},
run() {
console.log("Hello World!");
},
});

runMain(main);
```

### Lazy Load Commands

For large CLI apps, you may want to only load the command that is being executed.

First, create a command in a file and export it.

```js
import { defineCommand } from "citty";

export default defineCommand({
meta: {
name: "sub",
description: "Sub command",
},
run({ args }) {
console.log(`Hello ${args.name}!`);
},
});
```

Then, create the main command and import the sub command.

```js
const main = defineCommand({
meta: {
name: "hello",
version: "1.0.0",
description: "My Awesome CLI App",
},
commands: {
sub: () => import("./sub.js").then((m) => m.default), // Lazy Import Sub Command
},
});
```

Now, when you run `hello sub`, the sub command will be loaded and executed. This avoid to load all commands at once.

### Publish CLI App as an Executable

You must first bundle your CLI app. To do so, you can use [`unjs/unbuild`](https://github.com/unjs/unbuild).

Then, you must create a file named `index.mjs` in a folder named `bin` at the root of your package. This file must export the main command from the `dist` build.

```js
#!/usr/bin/env node

import { runMain } from '../dist/index.mjs'

runMain()
```

Then, you will need to update your `package.json` file to enable the usage as a CLI:

```json
{
"type": "module",
"bin": "./bin/index.mjs",
// Name of the CLI will be the name of the package. You can provide an object to change the name.
// @see https://docs.npmjs.com/cli/v10/configuring-npm/package-json#bin
// "bin": {
// "my-cli": "./bin/index.mjs"
// },
"files": [
"bin",
"dist"
]
}
```

You're ready to publish your CLI app to npm!

## Utils

### `defineCommand`

`defineCommand` is a type helper for defining commands.
A type helper for defining commands.

### `runMain`

Runs a command with usage support and graceful error handling.

### `createMain`

Create a wrapper around command that calls `runMain` when called.
Create the main command that can be executed later. Return a [`runMain`](#runmain) function.

### `runCommand`

Expand Down

0 comments on commit 26a44f2

Please sign in to comment.