Spis treści
- Czym jest CLI?
- OK, ale po co mi to?
- Popularne CLI
- Nasze CLI
- Jak zacząć?
- Komendy
- Deploy
- Czy warto korzystać z CLI?
Czym jest CLI?
CLI (ang. Command Line Interface) to interfejs, dzięki któremu możemy komunikować się z aplikacją za pomocą terminalu. Większość systemów operacyjnych ma taki interfejs wbudowany, dostępny dla użytkownika. Jest to nic innego jak zbiór funkcji, które użytkownik może wykonać z wykorzystaniem wiersza poleceń zamiast rozbudowanego interfejsu graficznego.
Opis | Windows | Linux |
---|---|---|
Wyświetlanie listy plików w aktywnym katalogu | dir |
ls |
Kopiowanie pliku | copy |
cp |
Przenoszenie lub zmiana nazwy pliku | ren |
mv |
Zmiana uprawnień do pliku | attrib |
chmod |
Zakończenie aktywnego procesu | taskkill /IM code.exe |
kill -9 |
OK, ale po co mi to?
Trafne pytanie. Jak pewnie widzisz, wszystkie wypisane wyżej komendy można z powodzeniem wykonać z użyciem interfejsu graficznego. Niemniej jednak mogą zdarzyć się sytuacje, w których wykonanie polecania będzie po prostu szybsze.
Kilka praktycznych przykładów:
- Zamknięcie aplikacji działającej na porcie 3000 - npx kill-port 3000
- Pobranie pliku -
wget -O shared-uploads-directory-wp.zip https://github.com/sebastiansiejek/shared-uploads-directory-wp/releases/download/1.0.5/shared-uploads-directory-wp.zip
- Zmiana uprawnień do wszystkich plików w katalogu /wp-uploads -
chmod 755 wp-uploads -R
Są też przypadki w których w ogóle nie mamy możliwości z korzystania z interfejsu graficznego np. podczas połączenia SSH
(ang. secure shell) z serwerem.
Wiele serwisów udostępnia swoje CLI, aby w prosty i szybki sposób użytkownik mógł zarządzać swoimi usługami.
Popularne CLI
Github - gh
- Tworzenie release -
gh release create <tag>
- Wyświetlanie issues -
gh issue list
- Przełączanie się na Pull Request -
gh pr checkout <id>
WordPress - wp
- Wyświetlanie informacji o zarejestrowanych typach postów -
wp post-type list
- Usuwanie użytkownika -
wp user delete <id>
- Regenerowanie miniatur -
wp media regenerate --yes
Vercel - vercel
- Logowanie
vercel login
- Deploy na środowisko testowe -
vercel dev
- Dodanie zmiennych środowiskowych
vercel env add [name] [environment]
Nasze CLI
Powodów, dla których warto stworzyć własne CLI, jest niewątpliwie sporo. Głównym czynnikiem jest z pewnością optymalizacja czasu pracy. Dobrze zrobione narzędzie może być wykorzystywane przez cały zespół. Dzięki czemu możemy wyeliminować powielane błędy towarzyszące przy ręcznym wykonywaniu komend. Tworzenie takiego zestawu komend jest znacznie szybsze niż tworzenie aplikacji z interfejsem graficznym.
Jedno z naszych CLI służy do zarządzania starterem WordPress. Umożliwia nam ono m.in. tworzenie komponentów z gotową strukturą, instalowanie zależności oraz konfigurowanie projektu.
Jak zacząć?
Do stworzenia własnego CLI wykorzystamy popularny framework oclif, który działa w środowisku node.js. Zawiera zestaw gotowych narzędzi, dzięki którym tworzenie naszego interfejsu będzie bajecznie proste!
Wymagania
Inicjalizacja
npx oclif generate <name>
- uruchamiamy tę komendę i postępujemy zgodnie z instrukcjami. Przypatrz się dokładnie, w jaki sposób oclif wyświetla pola do wpisania tekstu oraz wyboru wartości. Analogicznie będą wyglądały opcje w naszym CLI.
Po wypełnieniu wszystkich wymaganych pól naszym oczom powinna ukazać się wygenerowana struktura katalogów.
Uruchomienie testowego polecenia
Po inicjalizacji projektu możemy sprawdzić, czy pobrane pliki działają poprawnie, wpisując w terminalu ./bin/dev hello world
. Powinieneś ujrzeć wiadomość zwrotną.
Struktura katalogów
/bin
- Folder z plikami wykonywalnymi/src/commands
- Folder z komendami. Każdy podfolder oznacza nową komendę/test
- Folder z testami
Komendy
Każda komenda to nic innego jak klasa rozszerzająca klasę abstrakcyjną Command
z biblioteki @oclif/core
. Zawarta w niej asynchroniczna funkcja run()
jest wywoływana za każdym razem, gdy z poziomu CLI wywołujemy komendę dotyczącą danej klasy.
npx oclif generate command <name>
- generowanie struktury komendy oraz testu. Struktura katalogów komend sprawia, że będą one wykonywane w podanej kolejności np. rc component generate test
Argumenty
Do dyspozycji mamy również argumenty. Jest to nic innego jak statyczna tablica z obiektami w klasie komendy.
Przykład: rc component createarg1 arg2
static args = [
{
name: 'file', // name of arg to show in help and reference with args[name]
required: false, // make the arg required with `required: true`
description: 'output file', // help description
hidden: true, // hide this arg from help
parse: input => 'output', // instead of the user input, return a different value
default: 'world', // default value if no arg input
options: ['a', 'b'], // only allow input to be from a discrete set
}
]
Flagi
Są to dodatkowe opcje, które możemy wykorzystać podczas wywoływania komend. Podobnie jak w przypadku argumentów flagi, również definiuje się jako metodę statyczną w klasie komendy.
Przykład: rc component create--force --dev=test
static flags = {
name: Flags.string({
char: 'n', // shorter flag version
description: 'name to print', // help description for flag
hidden: false, // hide from help
multiple: false, // allow setting this flag multiple times
env: 'MY_NAME', // default to value of environment variable
options: ['a', 'b'], // only allow the value to be from a discrete set
parse: input => 'output', // instead of the user input, return a different value
default: 'world', // default value if flag not passed (can be a function that returns a string or undefined)
required: false, // make flag required (this is not common and you should probably use an argument instead)
dependsOn: ['extra-flag'], // this flag requires another flag
exclusive: ['extra-flag'], // this flag cannot be specified alongside this other flag
}),
// flag with no value (-f, --force)
force: Flags.boolean({
char: 'f',
default: true, // default value if flag not passed (can be a function that returns a boolean)
// boolean flags may be reversed with `--no-` (in this case: `--no-force`).
// The flag will be set to false if reversed. This functionality
// is disabled by default, to enable it:
// allowNo: true
}),
}
Interakcja
Do interakcji z użytkownikiem możemy wykorzystać zestaw gotowy funkcji prompt. Dzięki nim możemy wyświetlić pola do wpisania tekstu, a nawet listy z gotowymi opcjami z pomocą biblioteki inquirer. Takie dane są przechowywane w pamięci, dzięki czemu możemy z nich korzystać podobnie jak ze zmiennych.
(źródło: oclif.io/docs/prompting)
Obsługa błędów
Każdy nieobsłużony błąd przerywa działanie CLI, wyświetlając stosowny komunikat. W dokumentacji znajdziesz całych rozdział poświęcony temu zagadnieniu.
Testy
Do pisania testów najlepiej jest skorzystać @oclif/test
. Testy bazują na frameworku Mocha. Więcej informacji znajdziesz w dokumentacji.
Wskazówki
./bin/dev <command_ name>
- uruchomienie komendy w trybie developerskim.- Pamiętaj, że oclif działa w środowisku Node.js, dzięki czemu możesz korzystać z jego wszystkich udogodnień, takich jak wykonywanie zapytań ajax lub poruszanie się po katalogach systemu.
- Do wykonywania poleceń systemowych możemy skorzystać z biblioteki shelljs. Zapewnia ona wsparcie dla Windows, Linux oraz OS X.
W celach demonstracyjnych napisałem proste CLI do generowania komponentu w aplikacji React.
Deploy
Gotowy kod możemy udostępnić w serwisie npm, wykonując polecenie npm publish --access public
. Od teraz nasz kod jest dostępny jako publiczna paczka, dzięki czemu każdy (oczywiście z zainstalowanym Node.js) może zainstalować CLI na swoim komputerze. Do tego celu wystarczy uruchomić polecenie npm install -g @sebastiansiejek/rc
. Po instalacji możemy uruchomić nasze CLI wywołując polecenie rc
.
npm package: npmjs.com/package/@sebastiansiejek/rc
Czy warto korzystać z CLI?
Korzystając z CLI, możemy w znaczny sposób ułatwić, przyspieszyć, a może nawet uprzyjemnić naszą pracę. Jeśli przeklikiwanie się przez złożoną strukturę aplikacji zajmuje zbyt dużo czasu lub widzisz, że niektóre funkcje można połączyć i wykonywać jednym uniwersalnym poleceniem, być może warto zastanowić się nad stworzeniem własnego CLI. Dzięki prostocie oraz gotowym funkcjom, które dostarcza nam oclif, tworzenie takiego spersonalizowanego narzędzia jest proste i przyjemne. Zachęcam do zapoznania się z dokumentacją frameworka.