Giriş yap

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.

macbook -- -bash --- 64x17
 
mkdir node-cli cd node-cli npm init -y

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.

macbook -- -bash --- 64x17
 
touch index.js

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.

macbook -- -bash --- 64x17
 
nano index.js

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;

macbook -- -bash --- 64x17
 
node . hello world

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.

macbook -- -bash --- 64x17
 
npm link

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.

macbook -- -bash --- 64x17
 
hello hello world

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.

macbook -- -bash --- 64x17
 
touch .npmignore
// .npmignore

node_modules/

node_modules klasörümüzü hariç tuttuk projemizde. Artık paylaşabiliriz.

macbook -- -bash --- 64x17
 
npm publish

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;

macbook -- -bash --- 64x17
 
npm i hello_tayfun123 -g

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.

macbook -- -bash --- 64x17
 
touch whoami.js nano whoami.js
// whoami.js

#!/usr/bin/env node
    
console.log("Tayfun Erbilen - 26 yaşında");

Sembolik linklerimizi tekrar oluşturup test edelim.

macbook -- -bash --- 64x17
 
npm link

Şu komutları çalıştırıp test edebilirsiniz;

macbook -- -bash --- 64x17
 
hello_tayfun123 benkimim

Dilerseniz yeni eklediklerinizde birlikte NPM'deki paketinizi güncelleyebilirsiniz. İlk olarak versiyonu güncelleyelim.

macbook -- -bash --- 64x17
 
npm version 1.0.1

Şimdide yeniden publish edelim.

macbook -- -bash --- 64x17
 
npm publish

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;

macbook -- -bash --- 64x17
 
ptphp trim ptcss all pthtml b

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.

macbook -- -bash --- 64x17
 
mkdir prototurk cd prototurk npm init -y

Daha sonra dosyalarımızı oluşturalım.

macbook -- -bash --- 64x17
 
touch php.js touch css.js touch html.js

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.

macbook -- -bash --- 64x17
 
npm i request chalk

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.

macbook -- -bash --- 64x17
 
npm link

Dosyalarımızı hazırlamaya başlamadan önce, çalıştırdığımız komutla birlikte birde parametre göndermemiz gerekecek bu örnekte. Yani;

macbook -- -bash --- 64x17
 
ptphp trim

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.

macbook -- -bash --- 64x17
 
ptphp trim [ 'trim' ]

Ü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.

macbook -- -bash --- 64x17
 
ptphp trim ptcss margin pthtml body

Artık publish etmeye hazırız. Yine .npmignore dosyasını oluşturup node_modules/ klasörümüzü hariç tutuyoruz.

macbook -- -bash --- 64x17
 
touch .npmignore
// .npmignore
        
node_modules/

Artık publish etmeye hazırız.

macbook -- -bash --- 64x17
 
npm publish + [email protected]

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;

macbook -- -bash --- 64x17
 
npm i prototurk

Kullanımları ise;

macbook -- -bash --- 64x17
 
ptphp trim ptcss all pthtml strong

Keyifli ve anlaşılır bir yazı olması dileğiyle, iyi çalışmalar :)

Tayfun Erbilen
30 gün önce yazdı. Son güncelleme: 29 gün önce