Add Prettier and ESLint tooling (Refs #77)

This commit is contained in:
2026-10-09 15:56:13 -04:00
parent 8ed059b8d3
commit 16469e2d43
711 changed files with 99737 additions and 28286 deletions
+60 -15
View File
@@ -14,7 +14,8 @@ export const KNOWN_LOGS = {
} as const;
export type LogKey = keyof typeof KNOWN_LOGS;
export const gameLogKey = (server: string): LogKey => gameOfServer(server) === 't6' ? 'games_zm' : 'games_sp';
export const gameLogKey = (server: string): LogKey =>
gameOfServer(server) === 't6' ? 'games_zm' : 'games_sp';
export function isLogKey(v: string): v is LogKey {
return Object.prototype.hasOwnProperty.call(KNOWN_LOGS, v);
@@ -45,33 +46,62 @@ export function resolveLogPath(serverName: string, key: LogKey): string | null {
export interface TailResult {
lines: string[];
size: number;
mtime: string; // ISO
mtime: string; // ISO
truncated: boolean; // true when we didn't read from the start of the file
}
export interface LogCursor {
fileId: string; offset: number; size: number; modified: string;
anchorLength: number; anchorHash: string;
fileId: string;
offset: number;
size: number;
modified: string;
anchorLength: number;
anchorHash: string;
}
export interface LogChunk {
contentBase64: string; size: number; mtime: string; truncated: boolean;
cursor: LogCursor; reset: boolean;
contentBase64: string;
size: number;
mtime: string;
truncated: boolean;
cursor: LogCursor;
reset: boolean;
}
/** Bounded byte reads; an anchor before the offset detects copy-truncate and regrowth. */
export async function readLogChunk(path: string, cursor?: LogCursor): Promise<LogChunk | TailResult | null> {
export async function readLogChunk(
path: string,
cursor?: LogCursor
): Promise<LogChunk | TailResult | null> {
const remote = await nativeLogChunk(path, cursor);
if (remote !== undefined) return remote;
let file;
try { file = await open(path, 'r'); }
catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null; throw error; }
try {
file = await open(path, 'r');
} catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;
throw error;
}
try {
const st = await file.stat();
if (!st.isFile()) return null;
const fileId = `${st.dev}:${st.ino}`, modified = `${st.mtimeMs}:${st.ctimeMs}`, size = st.size;
const fileId = `${st.dev}:${st.ino}`,
modified = `${st.mtimeMs}:${st.ctimeMs}`,
size = st.size;
const mtime = st.mtime.toISOString();
if (cursor?.fileId === fileId && cursor.modified === modified && cursor.size === size && cursor.offset === size) {
return { contentBase64: '', size, mtime, truncated: cursor.offset > 0, cursor, reset: false };
if (
cursor?.fileId === fileId &&
cursor.modified === modified &&
cursor.size === size &&
cursor.offset === size
) {
return {
contentBase64: '',
size,
mtime,
truncated: cursor.offset > 0,
cursor,
reset: false
};
}
const hash = (value: Buffer) => createHash('sha256').update(value).digest('hex');
let reset = !cursor || cursor.fileId !== fileId || cursor.offset > size;
@@ -86,9 +116,24 @@ export async function readLogChunk(path: string, cursor?: LogCursor): Promise<Lo
const offset = start + read.bytesRead;
const anchor = Buffer.alloc(Math.min(256, offset));
await file.read(anchor, 0, anchor.length, offset - anchor.length);
return { contentBase64: content.subarray(0, read.bytesRead).toString('base64'), size, mtime, truncated: start > 0, reset,
cursor: { fileId, modified, size, offset, anchorLength: anchor.length, anchorHash: hash(anchor) } };
} finally { await file.close(); }
return {
contentBase64: content.subarray(0, read.bytesRead).toString('base64'),
size,
mtime,
truncated: start > 0,
reset,
cursor: {
fileId,
modified,
size,
offset,
anchorLength: anchor.length,
anchorHash: hash(anchor)
}
};
} finally {
await file.close();
}
}
const DEFAULT_TAIL_LINES = 200;