Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement clack DO NOT MERGE #6293

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
202a1ae
feat: add clack/core and is-unicode-supported
khendrikse Jan 9, 2024
c894a16
feat: add sisteransi
khendrikse Jan 9, 2024
96cd7bf
feat: add styles
khendrikse Jan 9, 2024
f3892f7
Merge branch 'main' into CP-101/design-system-clack-implementation
khendrikse Jan 9, 2024
4006972
feat: add styles
khendrikse Jan 9, 2024
eb4e6fe
chore: add tests to this branch for now
khendrikse Jan 10, 2024
456caa2
chore: convert api command to use clack (#6294)
khendrikse Jan 10, 2024
5c28195
Merge branch 'main' into CP-101/design-system-clack-implementation
khendrikse Jan 11, 2024
493a6a1
chore: updates for converting the api command (#6295)
khendrikse Jan 11, 2024
5f03f68
chore: convert unlink command (#6297)
khendrikse Jan 11, 2024
5d98d73
chore: convert link command (#6313)
khendrikse Jan 15, 2024
9f20c4d
chore: convert login command (#6320)
khendrikse Jan 15, 2024
8ec6718
Merge branch 'main' into CP-101/design-system-clack-implementation
khendrikse Jan 15, 2024
7b2bba2
chore: convert logout command (#6321)
khendrikse Jan 15, 2024
b8daf92
feat: convert status command to clack (#6323)
lemusthelroy Jan 17, 2024
45faf72
Merge branch 'main' into CP-101/design-system-clack-implementation
khendrikse Jan 17, 2024
937c198
feat: convert switch command to clack (#6326)
lemusthelroy Jan 18, 2024
d8e422c
chore: convert log command (#6324)
khendrikse Jan 19, 2024
28ae1ed
chore: converts watch and init commands to clack (#6346)
lemusthelroy Jan 26, 2024
c674a16
chore: convert sites:list and sites:delete to clack (#6350)
lemusthelroy Jan 29, 2024
5a5d4ff
Fix no git path for init command (#6357)
lemusthelroy Jan 30, 2024
76f952b
chore: in progress of converting command having updated types (#6358)
lemusthelroy Feb 1, 2024
bf0560f
chore: merge main
Mar 18, 2024
3f7e207
chore: convert dev command to clack (#6366)
lemusthelroy Mar 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/e2e-tests.yml
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [main]
pull_request:
branches: [main]
branches: [main, CP-101/design-system-clack-implementation]
schedule:
# check daily to notice potential package manager issues
- cron: '0 1 * * *' # At 01:00 daily
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration-tests.yml
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [main]
pull_request:
branches: [main]
branches: [main, CP-101/design-system-clack-implementation]

jobs:
integration:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yml
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [main]
pull_request:
branches: [main]
branches: [main, CP-101/design-system-clack-implementation]

jobs:
unit:
Expand Down
171 changes: 171 additions & 0 deletions STYLEGUIDE.md
@@ -0,0 +1,171 @@
# Styleguide (WIP)

This is a simple overview of different conventions we want to follow for commands in the Netlify CLI. This document will
start simple and grow over time.

## Starting your command

Each command starts by using the `intro` method. You can import it like this:

```js
import { intro } from '../../utils/styles/index.js'

export const basicCommand = () => {
intro('basic command')
// do stuff
}
```

Pass the name of the command to the `intro` method.

### Child commands

As some of our commands call other CLI commands, we will sometimes want to conditionally call `intro` depending on
whether or not the command is a child command. To do this, we use add a property to the `OptionValues` object called
`isChildCommand`. This property should be set to `true` when the command is a child command. This means that we can
conditionally call `intro` like this:

```js
import { intro } from '../../utils/styles/index.js'

export const basicCommand = (options) => {
!options.isChildCommand && intro('basic command')
// do stuff
}
```

Doing this ensures the CLI groups the messages together correctly and ensures two `intro` messages are not shown.

## Finishing your command

Each command should end by using the `outro` method to create a clear visual end for your command. You can import it
like this:

```js
import { intro, outro } from '../../utils/styles/index.js'

export const basicCommand = () => {
intro('basic command')
// do stuff
outro({ message: 'Your message', exit: true })
}
```

You don't need to call `outro` if your command throws an error, as `NetlifyLog.error()` automatically creates a clear
visual end for your command already. Outro must be called with an object:
`outro({ exit: true })` and you can pass a message to it with `outro({ exit: true, message: 'Your message' })`.

### Child commands

As some of our commands call other CLI commands, we will sometimes want to conditionally call `outro` depending
on whether or not the command is a child command. To do this, we add a property to the `OptionValues` object
called `isChildCommand`. This property should be set to `true` when the command is a child command. This means that we can
conditionally call `outro` like this:

```js
import { intro, outro } from '../../utils/styles/index.js'

export const basicCommand = (options) => {
!options.isChildCommand && intro('basic command')
// do stuff
if (options.isChildCommand) {
NetlifyLog.success('Your message')
}
else {
outro({ message: 'Your message', exit: true })
}
}
```

Doing this ensures the CLI groups the messages together correctly and ensures two `outro` messages are not shown.

## Other content

Any content that is logged to the console using `NetlifyLog` between the `intro` and `outro` methods will be visually
grouped together so it is clear that they all belong to the same command.

## Log to the console using `NetlifyLog`

Use our custom logger to log messages to the console. This will ensure that the CLI is consistent in its output and that
we can easily change the output format in the future. To do this, import `NetlifyLog` like this:

```js
import { NetlifyLog } from '../../utils/styles/index.js'
```

Logs work really well together with the `intro` and `outro` methods.

### `NetlifyLog.message()`

If you want to send a simple message to the console that does not need to stand out, use the `NetlifyLog.message()`
method. This will log a normal unstyled message.

### `NetlifyLog.info()`

To log a message that should stand out a bit more, use the `NetlifyLog.info()` method. This will log a message with a
little bit of styling.

### `NetlifyLog.success()`

To log a success message that informs the user that their command was successful, use the `NetlifyLog.success()` method.

### `NetlifyLog.step()`

If your command has multiple steps, you can use the `NetlifyLog.step()` method to log a message that informs the user
which step is currently running.

### `NetlifyLog.warn() and NetlifyLog.warning()`

To log a warning message that informs the user that something might be wrong, use the `NetlifyLog.warn()` or the
`NetlifyLog.warning()` method.

### `NetlifyLog.error()`

If your command throws an error, it should use the `NetlifyLog.error()` method. This will ensure that the error is
logged to the console and that the CLI exits with a non-zero exit code. When you throw an error you don't have to also
call `outro()`.

## Spinner

If your command is doing something that takes a while, you can use the `spinner` method to show a spinner to the user.
The spinner starts off with a message that you can pass to the `spinner` method. You can then update the message of the
spinner by calling `spinner.message()` method again with a new message. When your command is done, you can call the
`spinner` method again with, or without a message to stop the spinner.

```js
import { intro, outro, spinner } from '../../utils/styles/index.js'

export const basicCommand = async () => {
intro('basic command')
const loading = spinner()

loading.start('Doing a thing')
await doAThing()
loading.stop('Finished doing a thing')

outro()
}
```

## Asking for user input

There are several helpers available for asking the user for input. They are all available in the
`'./utils/styles/index.js'` file.

### select

The `select` method allows you to ask the user to select an option from a list of options. You can pass a list of
options to the `select` method and it will return the selected option.

```js
import { select } from '../../utils/styles/index.js'

const result = await select({
message: 'Select an option',
maxItems: 7,
options: list.map((thing) => ({
label: thing.name,
value: thing.id,
})),
})
```