@the-node-forge/url-shortener
Version:
A URL shortener that generates and stores unique aliases for long URLs, with optional expiration and custom alias support.
110 lines (109 loc) • 3.63 kB
JavaScript
;
/* eslint-disable space-before-function-paren */
// stores/redisStore.ts
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisStore = void 0;
/**
* RedisStore implements the StoreAdapter interface using Redis for persistence.
* Each method includes try/catch blocks to handle possible asynchronous errors.
*
* Note: Ensure that you have installed the optional 'redis' package if you plan to use this store.
*/
class RedisStore {
constructor(client) {
this.client = client;
}
async get(alias) {
try {
const data = await this.client.get(alias);
return data ? JSON.parse(data) : null;
}
catch (error) {
console.error(`Error getting alias ${alias} from Redis:`, error);
return null;
}
}
async set(alias, entry, override = false) {
try {
const exists = await this.has(alias);
if (exists && !override) {
throw new Error(`Alias "${alias}" already exists. Use override option to replace it.`);
}
const TTL_DIVIDER = 1000;
const ttl = entry.expiresAt
? Math.ceil((entry.expiresAt - Date.now()) / TTL_DIVIDER)
: undefined;
if (ttl && ttl > 0) {
await this.client.set(alias, JSON.stringify(entry), { EX: ttl });
}
else {
await this.client.set(alias, JSON.stringify(entry));
}
}
catch (error) {
console.error(`Error setting alias ${alias} in Redis:`, error);
throw error;
}
}
async delete(alias) {
try {
await this.client.del(alias);
}
catch (error) {
console.error(`Error deleting alias ${alias} from Redis:`, error);
}
}
async has(alias) {
try {
return (await this.client.exists(alias)) === 1;
}
catch (error) {
console.error(`Error checking alias ${alias} in Redis:`, error);
return false;
}
}
async list() {
const entries = {};
try {
const keys = await this.client.keys('*');
for (const key of keys) {
try {
const val = await this.client.get(key);
if (val)
entries[key] = JSON.parse(val);
}
catch (innerError) {
console.error(`Error parsing key ${key} in Redis:`, innerError);
}
}
}
catch (error) {
console.error('Error listing keys from Redis:', error);
}
return entries;
}
async clearExpired() {
try {
const keys = await this.client.keys('*');
const now = Date.now();
for (const key of keys) {
try {
const val = await this.client.get(key);
if (val) {
const entry = JSON.parse(val);
if (entry.expiresAt && now > entry.expiresAt) {
await this.client.del(key);
}
}
}
catch (innerError) {
console.error(`Error processing key ${key} during clearExpired in Redis:`, innerError);
}
}
}
catch (error) {
console.error('Error clearing expired keys in Redis:', error);
}
}
}
exports.RedisStore = RedisStore;