Files
BMAD-METHOD/tools/flattener/binary.js

81 lines
1.8 KiB
JavaScript

const fsp = require('node:fs/promises');
const path = require('node:path');
const { Buffer } = require('node:buffer');
/**
* Efficiently determine if a file is binary without reading the whole file.
* - Fast path by extension for common binaries
* - Otherwise read a small prefix and check for NUL bytes
* @param {string} filePath
* @returns {Promise<boolean>}
*/
async function isBinaryFile(filePath) {
try {
const stats = await fsp.stat(filePath);
if (stats.isDirectory()) {
throw new Error('EISDIR: illegal operation on a directory');
}
const binaryExtensions = new Set([
'.jpg',
'.jpeg',
'.png',
'.gif',
'.bmp',
'.ico',
'.svg',
'.pdf',
'.doc',
'.docx',
'.xls',
'.xlsx',
'.ppt',
'.pptx',
'.zip',
'.tar',
'.gz',
'.rar',
'.7z',
'.exe',
'.dll',
'.so',
'.dylib',
'.mp3',
'.mp4',
'.avi',
'.mov',
'.wav',
'.ttf',
'.otf',
'.woff',
'.woff2',
'.bin',
'.dat',
'.db',
'.sqlite',
]);
const extension = path.extname(filePath).toLowerCase();
if (binaryExtensions.has(extension)) return true;
if (stats.size === 0) return false;
const sampleSize = Math.min(4096, stats.size);
const fd = await fsp.open(filePath, 'r');
try {
const buffer = Buffer.allocUnsafe(sampleSize);
const { bytesRead } = await fd.read(buffer, 0, sampleSize, 0);
const slice = bytesRead === sampleSize ? buffer : buffer.subarray(0, bytesRead);
return slice.includes(0);
} finally {
await fd.close();
}
} catch (error) {
console.warn(`Warning: Could not determine if file is binary: ${filePath} - ${error.message}`);
return false;
}
}
module.exports = {
isBinaryFile,
};