Skip to content
This repository was archived by the owner on Aug 2, 2025. It is now read-only.

Commit b48d616

Browse files
committed
Feat: Live Log endpoint and adjustments
1 parent ede35ba commit b48d616

7 files changed

Lines changed: 147 additions & 202 deletions

File tree

bun.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/core/utils/logger.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import path from "path";
33
import chalk, { ChalkInstance } from "chalk";
44
import { dbFunctions } from "../database/repository";
55
import wrapAnsi from "wrap-ansi";
6+
import { logToClients } from "~/routes/live-logs";
7+
import { logStreamData } from "~/typings/websocket";
8+
9+
const ansiRegex = /\x1B\[[0-?9;]*[mG]/g;
610

711
// Change to false here if dont want the spacing on a wrapped line
812
const padNewlines: boolean = true;
@@ -80,31 +84,40 @@ export const logger = createLogger({
8084
message = `[ ${chalk.greenBright("Plugin")} ] ${message}`;
8185
}
8286

87+
const logStreamData: logStreamData = {
88+
timestamp: timestamp as string,
89+
level: level as string,
90+
message: (message as string).replace(ansiRegex, ""),
91+
file: file as string,
92+
line: line as number,
93+
};
94+
95+
logToClients(logStreamData);
96+
8397
const paddedLevel = level.toUpperCase().padEnd(5);
8498
const coloredLevel = (levelColors[level] || chalk.white)(paddedLevel);
8599
const coloredContext = chalk.cyan(`${file as string}:${line as number}`);
86100
const coloredTimestamp = chalk.yellow(timestamp);
87101

88102
if (process.env.NODE_ENV !== "dev") {
89103
return `${coloredLevel} [ ${coloredTimestamp} ] - ${chalk.gray(
90-
message,
104+
message
91105
)} - [ ${coloredContext} ]`;
92106
}
93107

94108
const prefix = `${paddedLevel} [ ${timestamp} ] - `;
95109
const prefixLength = prefix.length;
96110
const formattedMessage = formatTerminalMessage(
97111
message as string,
98-
prefixLength,
112+
prefixLength
99113
);
100-
const ansiRegex = /\x1B\[[0-?9;]*[mG]/g;
101114

102115
try {
103116
dbFunctions.addLogEntry(
104117
(level as string).replace(ansiRegex, ""),
105118
(message as string).replace(ansiRegex, ""),
106119
(file as string).replace(ansiRegex, ""),
107-
line as number,
120+
line as number
108121
);
109122
} catch (error) {
110123
// Use console.error to avoid recursive logging
@@ -113,7 +126,7 @@ export const logger = createLogger({
113126
}
114127

115128
return `${coloredLevel} [ ${coloredTimestamp} ] - ${formattedMessage} - [ ${coloredContext} ]`;
116-
}),
129+
})
117130
),
118131
transports: [new transports.Console()],
119132
});

src/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import trpcRouter from "~/core/trpc";
1616
import { config } from "./typings/database";
1717
import { validateApiKey } from "./middleware/auth";
1818
import { monitorDockerEvents } from "./core/docker/monitor";
19+
import { liveLogs } from "./routes/live-logs";
20+
import { utilRoutes } from "./routes/utils";
1921

2022
console.log("");
2123
dbFunctions.init();
@@ -66,7 +68,7 @@ const DockStatAPI = new Elysia()
6668
},
6769
],
6870
},
69-
}),
71+
})
7072
)
7173
.onBeforeHandle(async (context) => {
7274
const { path, request, set } = context;
@@ -91,6 +93,8 @@ const DockStatAPI = new Elysia()
9193
.use(dockerWebsocketRoutes)
9294
.use(apiConfigRoutes)
9395
.use(stackRoutes)
96+
.use(utilRoutes)
97+
.use(liveLogs)
9498
.get("/health", () => ({ status: "healthy" }), { tags: ["Utils"] })
9599
.onError(({ code, set, path }) => {
96100
if (code === "NOT_FOUND") {
@@ -115,18 +119,18 @@ async function startServer() {
115119

116120
if (apiKey === "changeme") {
117121
logger.warn(
118-
"Default API Key of 'changeme' detected. Please change your API Key via the `/config/update` route!",
122+
"Default API Key of 'changeme' detected. Please change your API Key via the `/config/update` route!"
119123
);
120124
}
121125

122126
DockStatAPI.listen(3000, ({ hostname, port }) => {
123127
console.log("----- [ ############## ]");
124128
logger.info(`DockStatAPI is running at http://${hostname}:${port}`);
125129
logger.info(
126-
`Swagger API Documentation available at http://${hostname}:${port}/swagger`,
130+
`Swagger API Documentation available at http://${hostname}:${port}/swagger`
127131
);
128132
logger.info(
129-
`tRPC Endpoint available at: http://${hostname}:${port}/trpc`,
133+
`tRPC Endpoint available at: http://${hostname}:${port}/trpc`
130134
);
131135
});
132136
} catch (error) {

src/middleware/auth.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export async function hashApiKey(apiKey: string): Promise<string> {
1616

1717
async function validateApiKeyHash(
1818
providedKey: string,
19-
storedHash: string,
19+
storedHash: string
2020
): Promise<boolean> {
2121
logger.debug("Validating API key hash");
2222
try {
@@ -30,7 +30,7 @@ async function validateApiKeyHash(
3030
}
3131

3232
async function getApiKeyFromDb(
33-
apiKey: string,
33+
apiKey: string
3434
): Promise<{ hash: string } | null> {
3535
const dbApiKey = (dbFunctions.getConfig() as config[])[0].api_key;
3636
logger.debug(`Querying database for API key: ${apiKey}`);
@@ -41,16 +41,20 @@ async function getApiKeyFromDb(
4141

4242
export async function validateApiKey(request: Request, set: set) {
4343
const apiKey = request.headers.get("x-api-key");
44-
logger.debug(`API key validation initiated`);
4544

4645
if (process.env.NODE_ENV != "production") {
46+
logger.warn(
47+
"API Key validation deactivated, since running in development mode"
48+
);
4749
return { apiKey };
4850
} else if (!apiKey) {
4951
logger.error(`API key missing from request ${request.url}`);
5052
set.status = 401;
5153
return { error: "API key required" };
5254
}
5355

56+
logger.debug(`API key validation initiated`);
57+
5458
try {
5559
const dbRecord = await getApiKeyFromDb(apiKey);
5660

0 commit comments

Comments
 (0)