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 :)