For the past two months, I've been developing a CLI (Command Line Interface)
Pomodoro timer and Todo application with Node.js. It will also have a TUI (Text
User Interface) to show statistics with various graphs and charts.
The main idea is: It should be able to create countdown timers and when a timer
finishes it'll give an alarm to remind me to take a break from work. Beside
that, it'll keep logs of my work sessions to show various stats.
It has the following architecture:
+-----------+ +--------+ +---------+
|DB (Sqlite)| | Timer | | Speaker |
+-----------+ +--------+ +---------+
\ | /
\ | /
+-----------+
| Server |
+-----------+
|^ |^
|| ||
v| v|
+-----+ +-----+
| CLI | | TUI |
+-----+ +-----+
The Server runs in the background as a service. The CLI and the TUI
communicates with the server over the IPC (TCP over Unix domain
socket or Windows Named Pipe) protocol. The server also needs to able to
broadcast data to it's client.
Though, I can just use a raw socket server with net.createServer
to do this
communication but it gets a little complicated after a while. Just as you
wouldn't use http.createServer
instead of a framework like Express, I
couldn't go further with this approach.
So, I decided to create my own IPC server framework (as a fun challenge) with
two goals in mind:
- Request handling feature like Express
- Data broadcasting to multiple clients
Alhamdulillah (praise be to God) after two weeks of work today I have published
the framework on npm. I named it Express-IPC.
Example usages:
server.js
const { Server } = require("express-ipc");
const socketPath = "./pipe";
const server = new Server();
const users = [
{ id: 1, name: "Alex" },
{ id: 2, name: "Alexa" },
];
server.get("/users/:id", ({ req, res }) => {
const id = Number(req.params.id);
const user = users.find((user) => user.id === id);
if (user) res.send(user);
else res.send({ message: `No user found with id: ${id}` }, { isError: true });
});
server.listen({
path: socketPath,
deleteSocketBeforeListening: true,
callback() {
console.log(`Server running on socket: ${server.socketPath}`);
},
});
client.js
const { Client } = require("express-ipc");
const socketPath = "./pipe";
main();
async function main() {
const client = new Client({ path: socketPath });
try {
const response = await client.get("/users/1");
console.log(response);
} catch (ex) {
console.log(ex);
}
client.close();
}
The toughest part was the request routing algorithm.
Sorry, it's too big to fit here and Dev.to doesn't support SVG files. I
tried to embed the flowchart here but it seems like, Dev.to neither supports
Mermaid nor can load my GitHub gist
about the flowchart. See the full chart
here.
Alhamdulillah, I was able to solve it after making a flowchart of the algorithm.
Honestly, It was super boring and took almost a day for me to solve.
As the server framework is completed, now it times for me to go back and
integrate it into my Pomodoro application.
I would love to hear your thoughts about this framework. If you have any
suggestion or feedback please let me know in the comment section đź’ť.
Credits: The background image is taken from Unsplash
Top comments (0)