Add Prettier and ESLint tooling (Refs #77)
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user