feat: update README, enhance setup scripts, and add dev utilities for improved workflow
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@ RUN npm run build
|
||||
|
||||
FROM nginx:1.29-alpine
|
||||
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY nginx.conf /etc/nginx/templates/default.conf.template
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ server {
|
||||
index index.html;
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://backend:3671/;
|
||||
proxy_pass http://${API_UPSTREAM}/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { computed, ref, watch, type Ref } from "vue";
|
||||
import { computed, ref, shallowRef, watch, type Ref } from "vue";
|
||||
|
||||
import { api, buildSocketUrl } from "../api";
|
||||
|
||||
@@ -11,6 +11,31 @@ type LogPlaneOptions = {
|
||||
onError: (error: unknown) => void;
|
||||
};
|
||||
|
||||
const LOG_RECONNECT_DELAY_MS = 1200;
|
||||
const LOG_FLUSH_DELAY_MS = 75;
|
||||
const MAX_LOG_LINES = 2500;
|
||||
const MAX_LOG_CHARS = 250_000;
|
||||
|
||||
function splitLogText(text: string) {
|
||||
return text === "" ? [] : text.split("\n");
|
||||
}
|
||||
|
||||
function trimLogLines(lines: string[]) {
|
||||
let next = lines.length > MAX_LOG_LINES ? lines.slice(-MAX_LOG_LINES) : lines;
|
||||
let totalChars = next.reduce(
|
||||
(count, line, index) => count + line.length + (index > 0 ? 1 : 0),
|
||||
0,
|
||||
);
|
||||
|
||||
while (totalChars > MAX_LOG_CHARS && next.length > 1) {
|
||||
const [removed = ""] = next;
|
||||
next = next.slice(1);
|
||||
totalChars -= removed.length + 1;
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
export function useControlPlaneLogs({
|
||||
token,
|
||||
selectedPort,
|
||||
@@ -21,20 +46,63 @@ export function useControlPlaneLogs({
|
||||
const logFilter = ref("");
|
||||
const logsPaused = ref(false);
|
||||
const logsCleared = ref(false);
|
||||
const logLines = shallowRef<string[]>([]);
|
||||
|
||||
let logSocket: WebSocket | null = null;
|
||||
let logReconnectTimer: number | null = null;
|
||||
let logFlushTimer: number | null = null;
|
||||
let pendingLogChunk = "";
|
||||
|
||||
const filteredLogs = computed(() => {
|
||||
const source = logs.value || "";
|
||||
const query = logFilter.value.trim().toLowerCase();
|
||||
if (!query) return source;
|
||||
return source
|
||||
.split("\n")
|
||||
if (!query) return logs.value;
|
||||
return logLines.value
|
||||
.filter((line) => line.toLowerCase().includes(query))
|
||||
.join("\n");
|
||||
});
|
||||
|
||||
function commitLogLines(lines: string[]) {
|
||||
const trimmed = trimLogLines(lines);
|
||||
logLines.value = trimmed;
|
||||
logs.value = trimmed.join("\n");
|
||||
}
|
||||
|
||||
function replaceLogs(text: string) {
|
||||
commitLogLines(splitLogText(text));
|
||||
}
|
||||
|
||||
function appendLogs(text: string) {
|
||||
if (!text) return;
|
||||
commitLogLines([...logLines.value, ...splitLogText(text)]);
|
||||
}
|
||||
|
||||
function flushPendingLogs() {
|
||||
if (!pendingLogChunk) return;
|
||||
appendLogs(pendingLogChunk);
|
||||
pendingLogChunk = "";
|
||||
}
|
||||
|
||||
function stopPendingFlush() {
|
||||
if (typeof window === "undefined" || logFlushTimer === null) return;
|
||||
window.clearTimeout(logFlushTimer);
|
||||
logFlushTimer = null;
|
||||
}
|
||||
|
||||
function scheduleLogFlush() {
|
||||
if (typeof window === "undefined" || logFlushTimer !== null) return;
|
||||
logFlushTimer = window.setTimeout(() => {
|
||||
logFlushTimer = null;
|
||||
flushPendingLogs();
|
||||
}, LOG_FLUSH_DELAY_MS);
|
||||
}
|
||||
|
||||
function resetLogBuffer() {
|
||||
stopPendingFlush();
|
||||
pendingLogChunk = "";
|
||||
logLines.value = [];
|
||||
logs.value = "";
|
||||
}
|
||||
|
||||
function parseLogFrame(raw: string): LogFrame | null {
|
||||
try {
|
||||
const payload = JSON.parse(raw);
|
||||
@@ -55,7 +123,7 @@ export function useControlPlaneLogs({
|
||||
if (port === null) return;
|
||||
try {
|
||||
if (!logsCleared.value) {
|
||||
logs.value = (await api.logs(port)).log;
|
||||
replaceLogs((await api.logs(port)).log);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!silent) onError(error);
|
||||
@@ -72,7 +140,7 @@ export function useControlPlaneLogs({
|
||||
logReconnectTimer = null;
|
||||
if (!token.value || logsPaused.value || selectedPort.value !== proxyPort) return;
|
||||
void openLogStream(proxyPort);
|
||||
}, 1200);
|
||||
}, LOG_RECONNECT_DELAY_MS);
|
||||
}
|
||||
|
||||
async function openLogStream(proxyPort: number) {
|
||||
@@ -98,10 +166,13 @@ export function useControlPlaneLogs({
|
||||
if (frame === null) return;
|
||||
if (frame.type === "snapshot") {
|
||||
if (logsCleared.value) return;
|
||||
logs.value = frame.log;
|
||||
resetLogBuffer();
|
||||
replaceLogs(frame.log);
|
||||
return;
|
||||
}
|
||||
logs.value += frame.log;
|
||||
|
||||
pendingLogChunk += frame.log;
|
||||
scheduleLogFlush();
|
||||
};
|
||||
|
||||
socket.onclose = (event) => {
|
||||
@@ -131,6 +202,8 @@ export function useControlPlaneLogs({
|
||||
window.clearTimeout(logReconnectTimer);
|
||||
logReconnectTimer = null;
|
||||
}
|
||||
stopPendingFlush();
|
||||
pendingLogChunk = "";
|
||||
if (logSocket === null) return;
|
||||
logSocket.onclose = null;
|
||||
logSocket.close();
|
||||
@@ -142,13 +215,13 @@ export function useControlPlaneLogs({
|
||||
}
|
||||
|
||||
function clearLogs() {
|
||||
logs.value = "";
|
||||
resetLogBuffer();
|
||||
logsCleared.value = true;
|
||||
}
|
||||
|
||||
function resetLogs() {
|
||||
stopLogStream();
|
||||
logs.value = "";
|
||||
resetLogBuffer();
|
||||
logFilter.value = "";
|
||||
logsPaused.value = false;
|
||||
logsCleared.value = false;
|
||||
@@ -158,7 +231,7 @@ export function useControlPlaneLogs({
|
||||
[selectedPort, token, logsPaused],
|
||||
([port, authToken, paused], [previousPort]) => {
|
||||
if (port !== previousPort) {
|
||||
logs.value = "";
|
||||
resetLogBuffer();
|
||||
logFilter.value = "";
|
||||
logsCleared.value = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user