@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
249 lines • 7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OverlayDir = void 0;
exports.getDir = getDir;
exports.releaseDir = releaseDir;
exports.openDir = openDir;
exports.newOverlayDir = newOverlayDir;
const type_1 = require("../type");
const overlayoptions_1 = require("../../../domain/fs/vo/overlayoptions");
/**
* OverlayDir entity - represents a merged directory from multiple filesystems
* TypeScript version of Go's Dir struct
*/
class OverlayDir {
constructor(options = {}) {
this._name = options.name || '';
this.fss = options.fss ? [...options.fss] : [];
this.dirOpeners = options.dirOpeners ? [...options.dirOpeners] : [];
if (options.info !== undefined) {
this.info = options.info;
}
this.merge = options.merge || overlayoptions_1.defaultDirMerger;
this.offset = 0;
this.fis = [];
this.closed = false;
}
/**
* Get file name
*/
name() {
return this._name;
}
/**
* Check if directory is closed
*/
isClosed() {
return this.closed || (this.fss.length === 0 && this.dirOpeners.length === 0);
}
/**
* Read directory entries
*/
async readdir(count) {
if (this.isClosed()) {
throw type_1.ErrFileClosed;
}
if (this.err) {
throw this.err;
}
// Load directory entries if not already loaded
if (this.offset === 0) {
await this.loadDirectoryEntries();
}
const remainingEntries = this.fis.slice(this.offset);
if (count <= 0) {
// Return all remaining entries
this.err = new Error('EOF');
if (this.offset > 0 && remainingEntries.length === 0) {
throw this.err;
}
return [...remainingEntries];
}
if (remainingEntries.length === 0) {
this.err = new Error('EOF');
throw this.err;
}
const result = remainingEntries.slice(0, count);
this.offset += result.length;
return result;
}
/**
* Read directory names
*/
async readdirnames(n) {
if (this.isClosed()) {
throw type_1.ErrFileClosed;
}
const entries = await this.readdir(n);
return entries.map(entry => entry.name());
}
/**
* Load directory entries from all filesystems
*/
async loadDirectoryEntries() {
// Read from filesystems directly (like Go version)
for (let i = 0; i < this.fss.length; i++) {
const fs = this.fss[i];
await this.readFromFilesystem(fs, null);
}
// Read from directory openers (fallback for compatibility)
for (let i = 0; i < this.dirOpeners.length; i++) {
const file = await this.dirOpeners[i]();
await this.readFromFilesystem(null, file);
}
}
/**
* Read directory entries from a specific filesystem or file
*/
async readFromFilesystem(fs, file) {
let f = file;
try {
if (!f && fs) {
// Convert "/" to "" for root directory access in BaseFs (like Go version)
const fsPath = this._name === '/' ? '' : this._name;
f = await fs.open(fsPath);
}
if (!f) {
return;
}
// Get directory entries
const entries = await f.readdir(-1);
// Merge with existing entries
this.fis = this.merge(this.fis, entries);
}
catch (error) {
// Continue if directory doesn't exist or can't be read
}
finally {
if (f && !file) {
// Only close if we opened it ourselves
await f.close();
}
}
}
/**
* Get file statistics
*/
async stat() {
if (this.isClosed()) {
throw type_1.ErrFileClosed;
}
if (this.info) {
return await this.info();
}
if (this.fss.length > 0) {
return await this.fss[0].stat(this._name);
}
throw new type_1.OverlayFsError('no filesystem available for stat', 'NO_FILESYSTEM');
}
/**
* Close directory
*/
async close() {
this.closed = true;
this.fss = [];
this.dirOpeners = [];
this.fis = [];
delete this.info;
this.offset = 0;
delete this.err;
}
/**
* Not supported operations for directories
*/
notSupported(operation) {
throw new type_1.OverlayFsError(`operation ${operation} not supported on directory "${this._name}"`, 'OPERATION_NOT_SUPPORTED');
}
// File interface methods that are not supported for directories
async read(buffer) {
this.notSupported('read');
}
async readAt(buffer, offset) {
this.notSupported('readAt');
}
async seek(offset, whence) {
this.notSupported('seek');
}
async write(buffer) {
this.notSupported('write');
}
async writeAt(buffer, offset) {
this.notSupported('writeAt');
}
async sync() {
this.notSupported('sync');
}
async truncate(size) {
this.notSupported('truncate');
}
async writeString(s) {
this.notSupported('writeString');
}
}
exports.OverlayDir = OverlayDir;
/**
* Directory pool for reusing OverlayDir instances
*/
class DirPool {
constructor() {
this.pool = [];
}
get() {
if (this.pool.length > 0) {
return this.pool.pop();
}
return new OverlayDir();
}
release(dir) {
// Reset the directory state
dir['fss'] = [];
dir['dirOpeners'] = [];
dir['fis'] = [];
delete dir['info'];
dir['offset'] = 0;
dir['_name'] = '';
delete dir['err'];
dir['closed'] = false;
this.pool.push(dir);
}
}
const dirPool = new DirPool();
/**
* Get a directory from the pool
*/
function getDir() {
return dirPool.get();
}
/**
* Release a directory back to the pool
*/
function releaseDir(dir) {
dirPool.release(dir);
}
/**
* Open a new merged directory
* TypeScript version of Go's OpenDir function
*/
async function openDir(name, merge, info, fss // Pass filesystems directly like Go version
) {
if (!info) {
throw new type_1.OverlayFsError('info function must not be null', 'INFO_REQUIRED');
}
const dir = getDir();
const options = {
name,
fss: [...fss], // Set filesystems directly
info,
merge: merge || overlayoptions_1.defaultDirMerger,
};
// Reinitialize the pooled directory
Object.assign(dir, new OverlayDir(options));
return dir;
}
/**
* Create a new OverlayDir instance
*/
function newOverlayDir(options = {}) {
return new OverlayDir(options);
}
//# sourceMappingURL=overlaydir.js.map