UNPKG

@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
"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