Let’s build a Timestamp Microservice using nodejs, expressjs and body-parser

Jobayer Ahmed Mickey
7 min readJul 15, 2018

--

এটা মুলত ফ্রিকোডক্যাম্পের Apis and Microservices Projects এর প্রথম প্রোজেক্ট। আমি রিসেন্টলি Apis and Microservices শেষ করেছি। তাই ভাবলাম যে সবগুলো প্রোজেক্ট এর একটা সিরিজ লিখি। এটা এই সিরিজের প্রথম পর্ব। চেষ্টা করবো সবগুলো পর্ব খুব তাড়াতাড়ি শেষ করতে। তো চলুন শুরু করি।

সবার প্রথমে আমাদের প্রোজেক্ট ফাইল বানাতে হবে। এখানে বলে রাখি আমি যেহেতু লিনাক্স ইউজার তাই আমি পুরো কাজটাই লিনাক্সে করছি। তবে আমার মনে হয় জানালা এবং আপেলেও একই রকম ভাবে করতে হয়। (জানালা অনেকদিন ব্যবহার করি না আর আপেল এ এইসব কাজ করার কোনো অভিজ্ঞতা নেই আমার।) তো আমরা এখন ডেক্সটপে একটা নতুন ফাইল বানাবো। ফাইলের নাম দিলাম timestamp_microservice. নিচের কমান্ড টি টার্মিনালে কপিপেস্ট করুন।

mkdir timestamp_microservice

আমাদের প্রোজেক্ট ডিরেক্টরী বানানো শেষ। এবার আমাদের কাজ হলো npm ইনিশিয়ালাইজ করা। অর্থাৎ আমাদের প্রোজেক্ট ফাইল এ একটা package.json ফাইল বানাতে হবে। ম্যানুয়্যালি না করে আমরা npm এর সাহায্য নেবো। নিচের কমান্ড টি টার্মিনাল এ কপিপেস্ট করুন এবং নিচের মত করে ইনফো দিয়ে দিন।

npm init

আপনারা যেনো অথরেও আমার নাম দিয়ে দিয়েন না 😛 ওইটাতে আপনাদের নাম ই দিয়েন।

এবার যেহেতু আমরা মেইন হিসেবে server.js ডিক্লিয়ার করেছি তাই আমাদের একটা server.js ফাইল বানাতে হবে। টার্মিনালে touch server.js দিলেই প্রোজেক্ট ডিরেক্টরিতে server.js নামের একটা ফাইল তৈরি হবে। আমি এই কাজের জন্য sublime text ইউজ করবো। তো এবার subl server.js টার্মিনালে লিখে এন্টার দিলেই server ফাইলটি সাবলাইম টেক্সট এ ওপেন হবে। এবার কাজের কাজ শুরু করা যাক।

সবার প্রথমে আমরা আমাদের ডিপেন্ডেন্সিগুলো ডিক্লিয়ার করবো। নিচের কোডটুকু আপনাদের টেক্সট এডিটরে লিখে ফেলুন। (চাইলেও কপি করতে পারবেন না 😆 😜 নিজের লিখতে হবে। 😛)

এবার আমরা আমাদের সার্ভারের পোর্ট ডিক্লিয়ার করবো। যেহেতু আমরা লোকালহোস্টে রান করছি, তাই আমাদের পোর্ট হবে 3000 (যদি আপনার 3000 তে কিছু রান না করা থাকে তবেই আপনি পোর্ট 3000 এ আপনার সার্ভার রান করাতে পারবেন।)

আমাদের কাজ প্রায় ৮০ ভাগ শেষ। এখানে PORT = process.env.PORT || 3000 দেয়ার কারন হলো আমরা যখন কোনো এপিআই বানাই তখন তা পাবলিশ করার জন্য আমরা একেকজন একেক environment চুজ করি। যেমন কেউ Heroku কেউবা আবার Glitch ইত্যাদিতে তাদের এপিআই হোস্ট করে। তো process.env.PORT দেয়ার বিশেসত্ব হলো আপনি যেই environment এই আপনার api হোস্ট করেন না কেন ও সেই environment এর পোর্ট টাই নিজে থেকে নিয়ে নেবে। আর || 3000 হলো যদি সে ওই environment থেকে কোনো পোর্ট রিটার্ন না পায় তবে সে ডিফল্ট হিসেবে 3000 কে ঠিক করে নেয়।

এখন আমাদের বাকি থাকলো শুধু রাউট ঠিক করা এবং ম্যাথম্যাটিক্যাল কিছু কাজ।

তবে তার আগে চলুন আমরা আগে দেখি আমাদের এতক্ষনের পরিশ্রম কতটুকু সফল হয়েছে। তার জন্য আমরা একটা গেট রিকোয়েস্ট করে দেখি। যদি আমরা আমাদের কাঙ্খিত রেজাল্ট পাই তবে সামনে এগোবো। গেট রিকোয়েস্টের নিচের কোডটুকু আমাদের server.js ফাইলে লিখে ফেলি।

এবার আমাদের কাজ হলো আমাদের প্রয়োজনীয় ডিপেন্ডেন্সিগুলো ইনিস্টল করে ফেলা। আমরা সবার শুরুতে Expressjs এবং body-parser নামের দুইটা ডিপেন্ডেন্সি ডিক্লিয়ার করেছিলাম। তো আমরা এবার এই তিনটা ডিপেন্ডেন্সি ইনিস্টল করাবো। তার জন্য নিচের কমান্ডটুকু টার্মিনালে কপিপেস্ট করুন।

npm i express body-parser — save

ইনিস্টলেশন শেষ হলে এখন আমাদের server.js ফাইল রান করতে হবে। এই ক্ষেত্রে আমি nodemon সাজেস্ট করবো। কারন নরমালি প্রতিবার server.js ফাইল আমাদের রান করার জন্য node server.js কমান্ড দিতে হবে। কিন্তু nodemon এ সবচেয়ে বড় সুবিধা হলো ইহা আপনার প্রতিবার ফাইল চেঞ্জের পরে সেভ করা মাত্রই অটো রিস্টার্ট নেবে। বার বার আপনাকে ম্যানুয়্যালী সার্ভার রিস্টার্ট দেয়া লাগবে না। আমি nodemon গ্লোবাল ইনিস্টল করে নেবো। লোকাল ইনিস্টল এ অসুবিধা হলো আমার অন্য কোনো প্রোজেক্টে nodemon লাগলে আমার আবার সেখানেও লোকাল ইনিস্টল করতে হবে। তবে আপনারা চাইলে লোকাল ইনিস্টল করতে পারেন।

লোকাল ইনিস্টল এর জন্যঃ

npm i nodemon — save

গ্লোবাল ইনিস্টল এর জন্যঃ

গ্লোবাল ইনিস্টল এ আপনাকে রুট এক্সেস দিতে হবে।

sudo npm i nodemon -g

nodemon ইনিস্টল হয়ে গেলে আমরা আমরা আমাদের প্রোজেক্ট ডিরেক্টরীতে টার্মিনাল ওপেন করে nodemon server.js কমান্ড টি রান করাবো।

যদি আমাদের সবকিছু ঠিক থাকে তবে টার্মিনালে App is listening on port 3000 লেখা আসবে।

এবার আমরা ব্রাউজার ওপেন করে http://localhost:3000/date এই URL এ গেলে আমরা নিচের মত কিছু দেখতে পাবো।

আমরা সফল। সুতরাং সামনে আগাইতে পারি। 😅

তো এবার আমাদের কাজ হলো, আমাদের প্রোজেক্টের মুল অংশে ফোকাস করা। এতক্ষন আমরা যা করলাম তা শুধুই সেটাপ। অনেকটা বয়লারপ্লেট বলা যায়। এবার আমরা আমাদের মুল কাজ টা করবো।

সবকিছুর আগে একটা জিনিশ বলে নি। আসলে এটা শুরুতে বলা উচিৎ ছিলো। কিন্তু শুরুতে বলিনাই কারন আমি চাই সবাই পুরো পোস্ট পড়ুক। তাই পোস্টের মাঝে বলছি। এই প্রোজেক্টে আমাদের কাজ হলো আমরা একটা API বানাবো। যেখানে আমরা একটা ডেট এর রিডাবল ভার্সন বা ইউনিক্স ভার্সন যেটাই ইনপুট করিনা কেন আমাদের API আমাদেরকে ওই ডেট এর রিডাবল ভার্সন এবং ইউনিক্স ভার্সন দুটোই জেসন ফরম্যাটে আউটপুট করবে। তো চলুন মুল কাহীনি শুরু করি।

তো আমরা আমাদের এই কাজের পুরোনো রাউট টাই ব্যবহার করবো। শুধু /date এর পরে আমরা date_values নামের একটা কুয়েরী নেবো। তো এই এখানে কুয়েরীটা আমাদের অনেকটা ইউজার ইনপুটের মত কাজ করবে। যেহেতু আমরা ইনপুট টাকে পরে কাজে লাগাবো তাই আমি শুরুতেই এটাকে date_value নামের একটা ভ্যারিয়েবল এ রেখে নিচ্ছি। এখন যেহেতু কুয়েরী চেঞ্জ করলে পেজ রিলোড হবে, তাই আমরা date_value কে কনস্ট্যান্ট ভ্যারিয়েবল হিসেবে ধরতে পারি। এবং আমাদের আরো দুইটা ভ্যারিয়েবল লাগবে। ন্যাচারাল ডেট আর ইউনিক্স ডেট ডিক্লিয়ার করার জন্য। এবং এদুটোর মান পরিবর্তনশীল। তাই এগুলোকে কনস্ট্যান্ট ভ্যারিয়েবল হিসেবে ধরা যাবে না।

এখন আমাদের কোড দেখতে এমন হবে।

এবার আমাদের চেক করতে হবে যে আমরা কুয়েরীতে যে ডেটা পাস করছি তার ডেটা টাইপ কি। কারন আমরা যদি রিডেবল ডেট ইনপুট করি তবে তার ডেটা টাইপ কখনোই Number হবে না। আবার ডেটের ইউনিক্স ভার্সন ইনপুট করলে তার ডেটা টাইপ কখনোই String হবে না। কেন হবে না?

কারন রিডেবল ডেট ফরম্যাট দুই রকম হতে পারে। ১ঃ 01 Jan 2018 অথবা 01–01–2018 বা 01/01/2018। তো এখন যদি এটা নম্বর ফরম্যাটে হতো তবে এখানে Jan স্ট্রিং এ আছে তাই সম্ভব না। আবার যদি 01–01–2018 বা 01/01/2018 নম্বর হতো তবে ব্যাপারটা শুন্য এক বিয়োগ শুন্য এক বিয়োগ দুইহাজার আঠেরো হতো বা এক ভাগ শুন্য এক ভাগ দুইহাজার আঠেরো হতো। এবং ইউনিক্স তো সর্বদা নম্বর ফরম্যাট ই হবে। কারন ওটা শুধু একগুচ্ছো নম্বরের সমষ্টি। তো ইনপুট নম্বর কিনা তা চেক করতে আমরা জাভাস্ক্রীপ্টের isNan() ফাংশনটি ব্যবহার করবো। isNaN এর কাজ হলো ও একটা ববলিন ভ্যালু পাস করবে যদি ওকে দেয়া আর্গুমেন্ট NaN হয় তবে ট্রু পাস করবে আর না হলে ফলস। NaN এর ফুল ফর্ম হলো Not-A-Number।

এখন, যদি আমাদের ইনপুট নম্বর না হয় তবে সেটা রিডাবল ডেট ভার্সন। তো আমরা জানি যে new Date() ফাংশনের ভিতর কোনো ডেট ভার্সন ইনপুট করলে new Date() আমাদেরকে ওই ডেট আউটপুট করে। এখানে প্রশ্ন থাকতে পারে যে আমরা তো রিডাবল ভার্সন ই ইনপুট করছি। তাহলে আমাদের আবার new Date() ফাংশনের কি দরকার? দরকার টা আসলে রিডাবল ভার্সন কে ইউনিক্স ভার্সনে কনভার্ট করার জন্য। যদি ডেট রিডাবল হয়, তবে ওই ডেটের টাইমের সাথে ১০০০ ভাগ দিলে আমরা ওই ডেটের ইউনিক্স ভার্সন পাবো। আর যদি ইনপুটকৃত ডেট ইউনিক্স হয় তবে তার সাথে ১০০০ গুন করলে আমরা রিডাবল ভার্সন পাবো। এবং সবশেষে আমাদের toLocaleDateString ফাংশন কল করতে হবে। কারন আমাদের শুধুমাত্র রিডাবল ডেট ভার্সন লাগবে। new Date() ফাংশন আমাদের এছাড়াও আরো অনেক কিছু রিটার্ন করে। এবং আমরা toLocaleDateString ফাংশনের ভিতর ‘en-us’ পাস করবো। কারন আমাদের স্ট্যান্ডার্ট ডেট ভার্সন দরকার। তো এবার আমাদের গেট রিকোয়েস্টের ভিতরে কোডটা হবে অনেকটা এমন।

এখন এখানে ছোটো একটু ঘাপলা আছে। রিডাবল ডেট ভার্সন বা natural_date আমাদের কে mm/dd/yyyy ফরম্যাটে ডেট রিটার্ন করবে। আমি পার্সোনালী এই ফরম্যাট টা পছন্দ করি না। আমার কাছে dd/mm/yyyy ই ভালো। তো আমরা এই mm/dd/yyyy কে dd/mm/yyyy তে কনভার্ট করতে natural_date কে split করবো। ভিউপয়েন্ট হবে ‘/’ কারন প্রতিটা সেকশন / দ্বারা আলাদা করা। split করার পরে আমরা ৩টা এলিমেন্টের একটা এ্যারে পাবো। যার জিরো ইন্ডেক্স হলো মাস, এবং প্রথম ইন্ডেক্স হলো দিন। তো আমরা যাস্ট এই মাস কে দিনের যায়গায় আর দিনকে মাসের যায়গায় নিয়ে গেলেই আমাদের কাজ খতম। এটা “moment.js” দিয়ে খুব সহজেই করা যায়। কিন্তু এখানে আমরা নিজেরাই এই ছোটো কাজটা করবো। কি দরকার সামান্য একটা ফরম্যাট চেঞ্জ করার জন্য গোটা একটা নোড মডিউল ইনিস্টল করার? 🐡

ফরম্যাট চেঞ্জ করার জন্য আমরা একটা ফাংশন বানাবো। যার আর্গুমেন্ট হিসেবে আমরা আমাদের ন্যাচারাল ডেট ভ্যারিয়েবলটাকে পাস করে দেবো। এবং ফাংশনটি আমাদের mm/dd/yyyy কে dd/mm/yyyy তে কনভার্ট করে রিটার্ন করে দেবে। তাহলে আমাদের কোডটা দাড়াবে এরকম

ব্যাস। কাজ শেষ। এবার /date রাউটে গিয়ে কুয়েরী বসান আর হাতে গরম ফলাফল উপভোগ করুন। স্বাদের জন্য পরিমানমত লবন, চিনি এবং লঙ্কাগুড়ো মিশিয়ে গরম পানিতে অল্পআচে সেদ্ধ করতে পারেন। সেদ্ধ হয়ে গেলে উপরে সামান্য চিলিসস দিয়ে গরম গরম পরিবেশন করুন আপনার কষ্ট করে বানানো Timestamp Microservice 😅

আমাদের প্রোজেক্টের সম্পুর্ন কোড। আপনি চাইলেও কপিপেস্ট করতে পারবেন না। নিজের টাইপ করতে হবে। 😅

আজকের মত বিদায়। আল্লাহ হাফেজ।

--

--

Jobayer Ahmed Mickey

Front-end Developer | UI/UX Designer | Amateur Blogger | Speed Cubist