NodeJS ile Komut Satırı (CLI) Aracı Oluşturmak
Bu yazımda sizlere, nodejs kullanarak, nasıl cli aracı oluşturabileceğimizi göstermek istiyorum. Bunu javascript ile yapabiliyor olmak heyecan verici :) Hiç uzatmadan başlayalım.
İlk olarak nodejs'i yüklemeniz gerekiyor. Bunun için buradan indirip işletim sisteminize göre kurulumunu yapın.
Nodejs'i kurduysanız, o zaman terminalinizi açın ve aşağıdaki komutları çalıştırın.
Bu komutların açıklaması;
mkdir node-cli
- node-cli adında bir klasör oluşturur
cd node-cli
- node-cli klasörüne girer
npm init -y
- node'un paket yöneticisi olan npm'i kullanarak bir package.json dosyası oluşturuyoruz.
Şimdi bir javascript dosyası oluşturalım.
Bu komutun açıklaması;
touch index.js
- index.js adında bir dosya oluşturur
Şimdi de index.js
dosyamızı açıp içerisine bir hello world yazdıralım.
nano index.js
- index.js dosyasını nano ile düzenlemek için terminalden açar. Siz normal bir editör yardımı ile de açıp aşağıdaki kodu yazabilirsiniz.
// index.js
console.log("hello world");
Artık çalıştırıp sonuca bakalım;
Burada nokta işareti koyduk, eğer dosyanız index.js
ise, nokta koyarakta çalıştırabilirsiniz. Ama örneğin dosya adımı hello.js
olsaydı o zaman node hello
ya da node hello.js
olarak çalıştırmamız gerekirdi.
// Çıktı: hello world
Şu an için node komutu olarak çağırıyoruz, ama bizim istediğimi kendimize özel bir şey yapmak. Bunun için index.js
dosyamızda şu şekilde değişiklik yapıyoruz;
#!/usr/bin/env node
console.log("hello world");
Bu sayede artık projemizi node komutu olmadan çalıştırabileceğiz.
Sıra geldi, package.json
dosyamızdaki değişikliğe. Dosyayı açıp şu satırları ekleyin;
{
name: "node-cli",
// ...
bin: "./index.js"
// ...
}
bin
, node projeleri için komut isimlerini belirler. Tek bir dosyamız olduğu için, name özelliğinin değeri shell komut adı olarak kullanılacak.
Bu yüzden name
'in değerini daha anlamlı şekilde değiştirelim. Örneğin hello_tayfun123
olarak belirleyebiliriz. Gerçi buda anlamlı olmadı ama npm'de olmayan random bir isim belirledim, siz kendi amacınıza uygun olarak belirlersiniz :) Belirlediğiniz isme dikkat edin, npm'de zaten olan bir paket adıysa, publish ederken hata alacaksınız. Merak etmeyin, hatayı en altta çözümüyle birlikte gösterdim.
{
name: "hello_tayfun123",
// ...
bin: "./index.js"
// ...
}
Sıra geldi, projemizi global olarak kullanıma sunmaya. Bunun için npm link
komutunu kullanacağız.
Bu komut bize proje dosyamız ve çalıştırılabilir komut ile arasında sembolik bir link oluşturacak. Artık yukarıda belirlediğimiz isim ile komutumuzu çalıştırmaya hazırız.
Projemiz içinde komut satırına hello
komutunu çalıştırdığımızda node .
ile aynı işlemi yaptığını göreceksiniz.
Tebrikler, en basitinden bir cli yapmış oldunuz kendinize :)
NPM'de Projeyi Paylaşma
Başka kullanıcılarında bu tool'umuzu kullanması için NPM'de yayınlayabiliriz. Ancak yayınlamadan önce bazı klasör ve dosyaları göndermek istemediğimizden, .npmignore
dosyası oluşturup burada belirteceğiz.
// .npmignore
node_modules/
node_modules
klasörümüzü hariç tuttuk projemizde. Artık paylaşabiliriz.
Eğer şöyle bir hata aldıysanız;
401 Unauthorized - PUT https://registry.npmjs.org/hello - You must be logged in to publish packages.
NPM'e giriş yapmanız gerekiyordur. O zaman npm login
komutunu çalıştırıp kullanıcı adı ve şifrenizi yazarak giriş yapın. Eğer hesabınız yok ise, önce buradan bir hesap açın tabi :)
Eğer şu şekilde bir hata alıyorsanız;
npm ERR! 403 Forbidden - PUT https://registry.npmjs.org/hello - You do not have permission to publish "hello". Are you logged in as the correct user?
Bilin ki bu isimde bir paket zaten var ve sahibi siz değilsiniz :) Gidip package.json'dan adını değiştirin, ve son olarak yeniden npm publish
yapıp yayınlayın.
Tebrikler, artık başkaları şu şekilde projemize erişebilir;
Nasıl kullanılır?
Artık başkaları da sizin paketinizi aşağıdaki gibi kurup kullanmaya başlayabilirler;
Kullanırken de direk hello_tayfun123
yazmaları yeterli :) Tabi bu örnekte isimlendirme saçma oldu ama neyse.
Birden Fazla Komut Eklemek
Yaptığımız örnekte tek bir komut vardı, oda hello_tayfun123
komutu :) Dilerseniz birden fazla komutta tanımlayabilirsiniz. Bunun için package.json
dosyamızı şu şekilde düzenleyelim;
{
name: "hello",
// ...
bin: {
"hello_tayfun123": "./index.js",
"benkimim": "./whoami.js"
}
// ...
}
Artık bin
özelliğimiz bir obje ve içinde 2 komut barındırıyor. Bunlar hello_tayfun123
ve benkimim
komutları.
Şimdi whoami.js
dosyasını oluşturup içerisine yine konsola bir şeyler yazdıralım.
// whoami.js
#!/usr/bin/env node
console.log("Tayfun Erbilen - 26 yaşında");
Sembolik linklerimizi tekrar oluşturup test edelim.
Şu komutları çalıştırıp test edebilirsiniz;
Dilerseniz yeni eklediklerinizde birlikte NPM'deki paketinizi güncelleyebilirsiniz. İlk olarak versiyonu güncelleyelim.
Şimdide yeniden publish edelim.
Gerçek Hayattan Bir Örnek Yapalım
Bu işlerin nasıl işlediğini anladığımıza göre, daha yararlı bir paket oluşturabiliriz. Benim yapacağım örnekte prototürk'ün json servisini kullanacağım. Biliyorsunuz html, css ve php'de json dosyalarımız var. Bende oluşturacağım pakette bu json'lardan bilgileri alıp açıklamalarını göstereceğim. Yani örneğin;
Gibi komutlar ile o fonksiyonun, özelliğin ya da etiketin açıklamalarını bu json dosyalarından çekip göstereceğim. Bir şekilde takıldığınızda açıklamayı okuyup çözüme ulaşabilirsiniz. Bunun için hemen başlayalım.
İlk olarak projemizi oluşturalım.
Daha sonra dosyalarımızı oluşturalım.
Bu paketimizi 2 bağımlılığı olacak. Birisi istekleri yönetmek için request
paketi, bir diğeri ise komut satırında stil uygulamak için chalk
paketi. Dilerseniz bunları kuralım.
Sembolik linklerini oluşturmadan önce package.json
dosyamızı şöyle güncelleyelim.
{
"name": "prototurk",
// ...
"bin": {
"ptcss": "./css.js",
"ptphp": "./php.js",
"pthtml": "./html.js"
},
// ...
}
Ve sembolik linklerimizi oluşturalım.
Dosyalarımızı hazırlamaya başlamadan önce, çalıştırdığımız komutla birlikte birde parametre göndermemiz gerekecek bu örnekte. Yani;
Burada trim
değerini almam gerek. O yüzden php.js
dosyamızı açalım ve şöyle bir kod yazalım.
#!/usr/bin/env node
const request = require('request');
const chalk = require('chalk');
const args = process.argv.slice(2);
console.log(args);
Gönderilen parametreleri almak için process.argv
altına bakıyoruz. İlk ikisini es geçiyoruz. Ondan sonra gelenler, bizim gönderdiğimiz parametreler olacak. Şimdi çalıştırıp bakalım.
Üstte 2 adet daha sabit tanımladık, bunlar bizim bağımlılıklarımız. Kullanmak üzere çağırdık. Şimdi parametreyi de alabildiğimize göre kodumuuzu şöyle düzenleyelim.
#!/usr/bin/env node
const request = require('request');
const chalk = require('chalk');
const args = process.argv.slice(2);
// eğer parametre gönderilmemiş ise
if (typeof args[0] === 'undefined'){
return console.log(chalk.bgRed.black('Hatalı kullanım\nÖrnek kullanım ---> ptphp [fonksiyon]'));
}
// parametre göndermiş ise json dosyasın çekip işlem yap
request.get(`https://prototurk.com/api/php/${args[0]}.json`, function (error, response, body) {
switch(response.statusCode){
case 200:
let data = JSON.parse(body);
console.log(chalk.bgGreen.black(`${data.title}\n${data.description}`));
break;
case 404:
console.log(chalk.bgWhiteBright.black(`${args[0]} fonksiyonunun detaylarına ulaşılamıyor :(`));
break;
}
});
Burada kodlar karmaşık gözükmesin gözünüze. İstekleri yönetmek için kullandığımız request
paketinin kullanımlarına buradan, komut satırı stil işlemleri için kullandığımız chalk
paketinin detaylarına ise buradan bakabilirsiniz. Geri kalan zaten basit javascript işlemleri :)
Şimdi de css.js
dosyamızı düzenleyelim.
#!/usr/bin/env node
const request = require('request');
const chalk = require('chalk');
const args = process.argv.slice(2);
// eğer parametre gönderilmemiş ise
if (typeof args[0] === 'undefined'){
return console.log(chalk.bgRed.black('Hatalı kullanım\nÖrnek kullanım ---> ptcss [özellik]'));
}
// parametre göndermiş ise json dosyasın çekip işlem yap
request.get(`https://prototurk.com/api/css/${args[0]}.json`, function (error, response, body) {
switch(response.statusCode){
case 200:
let data = JSON.parse(body);
console.log(chalk.bgGreen.black(`${data.title}\n${data.description}`));
break;
case 404:
console.log(chalk.bgWhiteBright.black(`${args[0]} özelliğinin detaylarına ulaşılamıyor :(`));
break;
}
});
Son olarak html.js
dosyamızı;
#!/usr/bin/env node
const request = require('request');
const chalk = require('chalk');
const args = process.argv.slice(2);
// eğer parametre gönderilmemiş ise
if (typeof args[0] === 'undefined'){
return console.log(chalk.bgRed.black('Hatalı kullanım\nÖrnek kullanım ---> pthtml [özellik]'));
}
// parametre göndermiş ise json dosyasın çekip işlem yap
request.get(`https://prototurk.com/api/html/${args[0]}.json`, function (error, response, body) {
switch(response.statusCode){
case 200:
let data = JSON.parse(body);
console.log(chalk.bgGreen.black(`${data.title}\n${data.description}`));
break;
case 404:
console.log(chalk.bgWhiteBright.black(`${args[0]} etiketinin detaylarına ulaşılamıyor :(`));
break;
}
});
Evet, artık şu şekilde testlerimizi yapabiliriz.
Artık publish etmeye hazırız. Yine .npmignore
dosyasını oluşturup
// .npmignore
node_modules/
Artık publish etmeye hazırız.
Tebrikler, benimle birlikte prototurk'ün paketini geliştirdiniz :) Artık sizde bu paketi kurup, takıldığınız yerde siteye bile girmeye gerek kalmadan terminalden açıklamalarına bakabilirsiniz.
Kurmak için;
Kullanımları ise;
Keyifli ve anlaşılır bir yazı olması dileğiyle, iyi çalışmalar :)