import fs from 'fs/promises';
import { normalizeLineEndings } from './utils.js';
export async function tailFile(filePath, numLines) {
const CHUNK_SIZE = 1024;
const stats = await fs.stat(filePath);
const fileSize = stats.size;
if (fileSize === 0)
return '';
const fileHandle = await fs.open(filePath, 'r');
try {
const lines = [];
let position = fileSize;
let chunk = Buffer.alloc(CHUNK_SIZE);
let linesFound = 0;
let remainingText = '';
while (position > 0 && linesFound < numLines) {
const size = Math.min(CHUNK_SIZE, position);
position -= size;
const { bytesRead } = await fileHandle.read(chunk, 0, size, position);
if (!bytesRead)
break;
const readData = chunk.slice(0, bytesRead).toString('utf-8');
const chunkText = readData + remainingText;
const chunkLines = normalizeLineEndings(chunkText).split('\n');
if (position > 0) {
remainingText = chunkLines[0];
chunkLines.shift();
}
for (let i = chunkLines.length - 1; i >= 0 && linesFound < numLines; i--) {
lines.unshift(chunkLines[i]);
linesFound++;
}
}
return lines.join('\n');
}
finally {
await fileHandle.close();
}
}
export async function headFile(filePath, numLines) {
const fileHandle = await fs.open(filePath, 'r');
try {
const lines = [];
let buffer = '';
let bytesRead = 0;
const chunk = Buffer.alloc(1024);
while (lines.length < numLines) {
const result = await fileHandle.read(chunk, 0, chunk.length, bytesRead);
if (result.bytesRead === 0)
break;
bytesRead += result.bytesRead;
buffer += chunk.slice(0, result.bytesRead).toString('utf-8');
const newLineIndex = buffer.lastIndexOf('\n');
if (newLineIndex !== -1) {
const completeLines = buffer.slice(0, newLineIndex).split('\n');
buffer = buffer.slice(newLineIndex + 1);
for (const line of completeLines) {
lines.push(line);
if (lines.length >= numLines)
break;
}
}
}
if (buffer.length > 0 && lines.length < numLines)
lines.push(buffer);
return lines.join('\n');
}
finally {
await fileHandle.close();
}
}