@lyleunderwood/filereader-polyfill
Version:
W3C File API specification compliant FileReader polyfill for Node.js environments
99 lines • 3.94 kB
JavaScript
import { basename } from 'path';
export class File extends Blob {
constructor(fileBitsOrPath, fileName, options) {
if (typeof fileBitsOrPath === 'string') {
// File path constructor - defer file system access
const filePath = fileBitsOrPath;
super([], { type: '' }); // Will be overridden by file content
this.name = basename(filePath);
this.lastModified = Date.now(); // Will be updated when file is accessed
this._path = filePath;
}
else {
// Standard Web API constructor
super(fileBitsOrPath, options);
this.name = fileName || '';
this.lastModified = options?.lastModified ?? Date.now();
}
}
get path() {
return this._path;
}
// Helper method to get file stats and update lastModified
async _getFileStats() {
if (!this._path)
return null;
try {
const { stat } = await import('fs/promises');
const stats = await stat(this._path);
// Update lastModified with actual file time (mutating readonly property)
this.lastModified = stats.mtime.getTime();
return stats;
}
catch (error) {
throw new DOMException(`Failed to read file: ${error}`, 'NotReadableError');
}
}
// Override arrayBuffer to read from file if path is available
async arrayBuffer() {
if (this._path) {
await this._getFileStats(); // This will throw DOMException if file doesn't exist
try {
const { readFile } = await import('fs/promises');
const buffer = await readFile(this._path);
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
}
catch (error) {
throw new DOMException(`Failed to read file: ${error}`, 'NotReadableError');
}
}
return super.arrayBuffer();
}
// Override stream to read from file if path is available
stream() {
if (this._path) {
const filePath = this._path;
const self = this;
return new ReadableStream({
async start(controller) {
try {
await self._getFileStats(); // This will throw DOMException if file doesn't exist
const { createReadStream } = require('fs');
const nodeStream = createReadStream(filePath);
nodeStream.on('data', (chunk) => {
controller.enqueue(new Uint8Array(chunk));
});
nodeStream.on('end', () => {
controller.close();
});
nodeStream.on('error', (error) => {
controller.error(new DOMException(`Failed to read file: ${error}`, 'NotReadableError'));
});
}
catch (error) {
controller.error(error);
}
},
cancel() {
// Stream will be cleaned up automatically
}
});
}
return super.stream();
}
// Override text to read from file if path is available
async text() {
if (this._path) {
await this._getFileStats(); // This will throw DOMException if file doesn't exist
try {
const { readFile } = await import('fs/promises');
return readFile(this._path, 'utf8');
}
catch (error) {
throw new DOMException(`Failed to read file: ${error}`, 'NotReadableError');
}
}
return super.text();
}
}
//# sourceMappingURL=File.js.map