cache.js: Map values serialise as '{}' under JSON.stringify, causing
emby:users to show 0 bytes and null item count in the status panel.
Convert Maps via Object.fromEntries before stringifying, and report
Map.size as itemCount.
index.js: JS and CSS served with Cache-Control: no-cache so browsers
always revalidate on load. ETag still prevents re-downloading unchanged
files — only a new deploy triggers an actual download.
75 lines
1.8 KiB
JavaScript
75 lines
1.8 KiB
JavaScript
const { logToFile } = require('./logger');
|
|
|
|
class MemoryCache {
|
|
constructor() {
|
|
this.store = new Map();
|
|
}
|
|
|
|
get(key) {
|
|
const entry = this.store.get(key);
|
|
if (!entry) return null;
|
|
if (Date.now() > entry.expiresAt) {
|
|
this.store.delete(key);
|
|
return null;
|
|
}
|
|
return entry.value;
|
|
}
|
|
|
|
set(key, value, ttlMs) {
|
|
this.store.set(key, {
|
|
value,
|
|
expiresAt: Date.now() + ttlMs
|
|
});
|
|
}
|
|
|
|
invalidate(key) {
|
|
this.store.delete(key);
|
|
}
|
|
|
|
clear() {
|
|
this.store.clear();
|
|
}
|
|
|
|
getStats() {
|
|
const now = Date.now();
|
|
const entries = [];
|
|
let totalSize = 0;
|
|
|
|
for (const [key, entry] of this.store.entries()) {
|
|
// Maps must be converted before JSON.stringify (which renders them as "{}")
|
|
const serializable = entry.value instanceof Map ? Object.fromEntries(entry.value) : entry.value;
|
|
const json = JSON.stringify(serializable);
|
|
const sizeBytes = Buffer.byteLength(json, 'utf8');
|
|
totalSize += sizeBytes;
|
|
const ttlRemaining = Math.max(0, entry.expiresAt - now);
|
|
const expired = now > entry.expiresAt;
|
|
let itemCount = null;
|
|
if (entry.value instanceof Map) {
|
|
itemCount = entry.value.size;
|
|
} else if (Array.isArray(entry.value)) {
|
|
itemCount = entry.value.length;
|
|
} else if (entry.value && typeof entry.value === 'object') {
|
|
if (Array.isArray(entry.value.records)) itemCount = entry.value.records.length;
|
|
else if (Array.isArray(entry.value.slots)) itemCount = entry.value.slots.length;
|
|
}
|
|
entries.push({
|
|
key,
|
|
sizeBytes,
|
|
itemCount,
|
|
ttlRemainingMs: ttlRemaining,
|
|
expired
|
|
});
|
|
}
|
|
|
|
return {
|
|
entryCount: this.store.size,
|
|
totalSizeBytes: totalSize,
|
|
entries
|
|
};
|
|
}
|
|
}
|
|
|
|
const cache = new MemoryCache();
|
|
|
|
module.exports = cache;
|