memoradb
Version:
A lightweight in-memory key-value store similar to Redis
130 lines (129 loc) • 4.55 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const net_1 = __importDefault(require("net"));
const port = process.argv[2] ? parseInt(process.argv[2]) : 6379;
class MemoraDB {
constructor() {
this.store = new Map();
this.expirations = new Map();
}
set(key, value, expiry = null) {
this.store.set(key, value);
if (expiry) {
this.setExpiry(key, expiry);
}
return "OK";
}
get(key) {
return this.store.has(key) ? this.store.get(key) : null;
}
del(key) {
this.store.delete(key);
this.expirations.delete(key);
return "OK";
}
expire(key, seconds) {
if (this.store.has(key)) {
this.setExpiry(key, seconds);
return 1;
}
return 0;
}
ttl(key) {
if (!this.expirations.has(key))
return -1;
const expiryTime = this.expirations.get(key);
const remaining = Math.ceil((expiryTime - Date.now()) / 1000);
return remaining > 0 ? remaining : -2;
}
persist(key) {
return this.expirations.delete(key) ? 1 : 0;
}
flushAll() {
this.store.clear();
this.expirations.clear();
return "OK";
}
incr(key) {
if (!this.store.has(key) || isNaN(Number(this.store.get(key)))) {
this.store.set(key, 0);
}
this.store.set(key, Number(this.store.get(key)) + 1);
return Number(this.store.get(key));
}
decr(key) {
if (!this.store.has(key) || isNaN(Number(this.store.get(key)))) {
this.store.set(key, 0);
}
this.store.set(key, Number(this.store.get(key)) - 1);
return Number(this.store.get(key));
}
setExpiry(key, seconds) {
const expiryTime = Date.now() + seconds * 1000;
this.expirations.set(key, expiryTime);
setTimeout(() => {
if (Date.now() >= expiryTime) {
this.del(key);
}
}, seconds * 1000);
}
}
const db = new MemoraDB();
const server = net_1.default.createServer((socket) => {
socket.write(`MemoraDB Server Connected\nMemoraDB:${port}> `);
let buffer = "";
socket.on("data", (data) => {
buffer += data.toString();
if (buffer.includes("\n")) {
const lines = buffer.split("\n");
buffer = lines.pop() || "";
lines.forEach((line) => {
var _a, _b;
const input = line.trim().split(/\s+/);
const command = (_a = input[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
let response = "Unknown command";
switch (command) {
case "SET":
response = db.set(input[1], input[2], input[3] === "EX" ? parseInt(input[4]) : null);
break;
case "GET":
response = ((_b = db.get(input[1])) === null || _b === void 0 ? void 0 : _b.toString()) || "(nil)";
break;
case "DEL":
response = db.del(input[1]);
break;
case "EXPIRE":
response = db.expire(input[1], parseInt(input[2])).toString();
break;
case "TTL":
response = db.ttl(input[1]).toString();
break;
case "PERSIST":
response = db.persist(input[1]).toString();
break;
case "FLUSHALL":
response = db.flushAll();
break;
case "INCR":
response = db.incr(input[1]).toString();
break;
case "DECR":
response = db.decr(input[1]).toString();
break;
default:
response = "Unknown command";
}
socket.write(response + "\nMemoraDB:" + port + "> ");
});
}
});
socket.on("end", () => console.log("Client disconnected"));
});
server.listen(port, () => {
console.log(`MemoraDB Server listening on port ${port}`);
});
exports.default = MemoraDB;