a cache for slack profile pictures and emojis

chore: biome format

dunkirk.sh 662896ee c28c12c0

verified
Changed files
+107 -59
src
handlers
routes
+24 -24
package.json
···
{
-
"name": "cachet",
-
"version": "0.3.2",
-
"scripts": {
-
"test": "echo \"Error: no test specified\" && exit 1",
-
"dev": "bun run --watch src/index.ts",
-
"start": "bun run src/index.ts",
-
"build": "bun build --compile --outfile dist/cachet --production ./src/index.ts"
-
},
-
"dependencies": {
-
"@sentry/bun": "^9.40.0",
-
"@tqman/nice-logger": "^1.0.7",
-
"@types/node-cron": "^3.0.11",
-
"bottleneck": "^2.19.5",
-
"elysia": "1.1.26",
-
"node-cron": "^3.0.3",
-
"sentry": "^0.1.2"
-
},
-
"devDependencies": {
-
"@types/bun": "latest"
-
},
-
"private": true,
-
"peerDependencies": {
-
"typescript": "^5"
-
}
+
"name": "cachet",
+
"version": "0.3.2",
+
"scripts": {
+
"test": "echo \"Error: no test specified\" && exit 1",
+
"dev": "bun run --watch src/index.ts",
+
"start": "bun run src/index.ts",
+
"build": "bun build --compile --outfile dist/cachet --production ./src/index.ts"
+
},
+
"dependencies": {
+
"@sentry/bun": "^9.40.0",
+
"@tqman/nice-logger": "^1.0.7",
+
"@types/node-cron": "^3.0.11",
+
"bottleneck": "^2.19.5",
+
"elysia": "1.1.26",
+
"node-cron": "^3.0.3",
+
"sentry": "^0.1.2"
+
},
+
"devDependencies": {
+
"@types/bun": "latest"
+
},
+
"private": true,
+
"peerDependencies": {
+
"typescript": "^5"
+
}
}
+53 -28
src/cache.ts
···
/**
* Discriminated union for all analytics cache data types
*/
-
type AnalyticsCacheData =
-
| { type: 'analytics'; data: FullAnalyticsData }
-
| { type: 'essential'; data: EssentialStatsData }
-
| { type: 'charts'; data: ChartData }
-
| { type: 'useragents'; data: UserAgentData };
+
type AnalyticsCacheData =
+
| { type: "analytics"; data: FullAnalyticsData }
+
| { type: "essential"; data: EssentialStatsData }
+
| { type: "charts"; data: ChartData }
+
| { type: "useragents"; data: UserAgentData };
/**
* Type-safe analytics cache entry
···
/**
* Type guard functions for cache data
*/
-
function isAnalyticsData(data: AnalyticsCacheData): data is { type: 'analytics'; data: FullAnalyticsData } {
-
return data.type === 'analytics';
+
function isAnalyticsData(
+
data: AnalyticsCacheData,
+
): data is { type: "analytics"; data: FullAnalyticsData } {
+
return data.type === "analytics";
}
-
function isEssentialStatsData(data: AnalyticsCacheData): data is { type: 'essential'; data: EssentialStatsData } {
-
return data.type === 'essential';
+
function isEssentialStatsData(
+
data: AnalyticsCacheData,
+
): data is { type: "essential"; data: EssentialStatsData } {
+
return data.type === "essential";
}
-
function isChartData(data: AnalyticsCacheData): data is { type: 'charts'; data: ChartData } {
-
return data.type === 'charts';
+
function isChartData(
+
data: AnalyticsCacheData,
+
): data is { type: "charts"; data: ChartData } {
+
return data.type === "charts";
}
-
function isUserAgentData(data: AnalyticsCacheData): data is { type: 'useragents'; data: UserAgentData } {
-
return data.type === 'useragents';
+
function isUserAgentData(
+
data: AnalyticsCacheData,
+
): data is { type: "useragents"; data: UserAgentData } {
+
return data.type === "useragents";
}
/**
···
getAnalyticsData(key: string): FullAnalyticsData | null {
const cached = this.cache.get(key);
const now = Date.now();
-
-
if (cached && now - cached.timestamp < this.cacheTTL && isAnalyticsData(cached.data)) {
+
+
if (
+
cached &&
+
now - cached.timestamp < this.cacheTTL &&
+
isAnalyticsData(cached.data)
+
) {
return cached.data.data;
}
return null;
···
getEssentialStatsData(key: string): EssentialStatsData | null {
const cached = this.cache.get(key);
const now = Date.now();
-
-
if (cached && now - cached.timestamp < this.cacheTTL && isEssentialStatsData(cached.data)) {
+
+
if (
+
cached &&
+
now - cached.timestamp < this.cacheTTL &&
+
isEssentialStatsData(cached.data)
+
) {
return cached.data.data;
}
return null;
···
getChartData(key: string): ChartData | null {
const cached = this.cache.get(key);
const now = Date.now();
-
-
if (cached && now - cached.timestamp < this.cacheTTL && isChartData(cached.data)) {
+
+
if (
+
cached &&
+
now - cached.timestamp < this.cacheTTL &&
+
isChartData(cached.data)
+
) {
return cached.data.data;
}
return null;
···
getUserAgentData(key: string): UserAgentData | null {
const cached = this.cache.get(key);
const now = Date.now();
-
-
if (cached && now - cached.timestamp < this.cacheTTL && isUserAgentData(cached.data)) {
+
+
if (
+
cached &&
+
now - cached.timestamp < this.cacheTTL &&
+
isUserAgentData(cached.data)
+
) {
return cached.data.data;
}
return null;
···
* Set analytics data in cache with type safety
*/
setAnalyticsData(key: string, data: FullAnalyticsData): void {
-
this.setCacheEntry(key, { type: 'analytics', data });
+
this.setCacheEntry(key, { type: "analytics", data });
}
/**
* Set essential stats data in cache with type safety
*/
setEssentialStatsData(key: string, data: EssentialStatsData): void {
-
this.setCacheEntry(key, { type: 'essential', data });
+
this.setCacheEntry(key, { type: "essential", data });
}
/**
* Set chart data in cache with type safety
*/
setChartData(key: string, data: ChartData): void {
-
this.setCacheEntry(key, { type: 'charts', data });
+
this.setCacheEntry(key, { type: "charts", data });
}
/**
* Set user agent data in cache with type safety
*/
setUserAgentData(key: string, data: UserAgentData): void {
-
this.setCacheEntry(key, { type: 'useragents', data });
+
this.setCacheEntry(key, { type: "useragents", data });
}
/**
···
// Check memory usage
const memUsage = process.memoryUsage();
const bytesToMiB = (bytes: number) => bytes / 1024 / 1024;
-
+
const heapUsedMiB = bytesToMiB(memUsage.heapUsed);
const heapTotalMiB = bytesToMiB(memUsage.heapTotal);
-
const heapPercent = heapTotalMiB > 0 ? (heapUsedMiB / heapTotalMiB) * 100 : 0;
+
const heapPercent =
+
heapTotalMiB > 0 ? (heapUsedMiB / heapTotalMiB) * 100 : 0;
const rssMiB = bytesToMiB(memUsage.rss);
const externalMiB = bytesToMiB(memUsage.external || 0);
const arrayBuffersMiB = bytesToMiB(memUsage.arrayBuffers || 0);
-
+
checks.memoryUsage = {
heapUsed: Math.round(heapUsedMiB),
heapTotal: Math.round(heapTotalMiB),
+6 -1
src/handlers/index.ts
···
if (detailed) {
const health = await cache.detailedHealthCheck();
-
const statusCode = health.status === "unhealthy" ? 503 : health.status === "degraded" ? 200 : 200;
+
const statusCode =
+
health.status === "unhealthy"
+
? 503
+
: health.status === "degraded"
+
? 200
+
: 200;
await recordAnalytics(statusCode);
return Response.json(health, { status: statusCode });
}
+24 -6
src/routes/api-routes.ts
···
details: {
type: "object",
properties: {
-
heapUsedMiB: { type: "number", description: "Precise heap used in MiB" },
-
heapTotalMiB: { type: "number", description: "Precise heap total in MiB" },
-
heapPercent: { type: "number", description: "Precise heap percentage" },
-
rssMiB: { type: "number", description: "Resident Set Size in MiB" },
-
externalMiB: { type: "number", description: "External memory in MiB" },
-
arrayBuffersMiB: { type: "number", description: "Array buffers in MiB" },
+
heapUsedMiB: {
+
type: "number",
+
description: "Precise heap used in MiB",
+
},
+
heapTotalMiB: {
+
type: "number",
+
description: "Precise heap total in MiB",
+
},
+
heapPercent: {
+
type: "number",
+
description: "Precise heap percentage",
+
},
+
rssMiB: {
+
type: "number",
+
description: "Resident Set Size in MiB",
+
},
+
externalMiB: {
+
type: "number",
+
description: "External memory in MiB",
+
},
+
arrayBuffersMiB: {
+
type: "number",
+
description: "Array buffers in MiB",
+
},
},
},
},