UNPKG

@push.rocks/smartfile

Version:

High-level file representation classes (SmartFile, StreamFile, VirtualDirectory) for efficient in-memory file management in Node.js using TypeScript. Works seamlessly with @push.rocks/smartfs for filesystem operations.

332 lines 23.7 kB
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; import * as plugins from './plugins.js'; /** * an vinyl file compatible in memory file class * Use SmartFileFactory to create instances of this class */ let SmartFile = (() => { let _classSuper = plugins.smartjson.Smartjson; let _path_decorators; let _path_initializers = []; let _path_extraInitializers = []; let _contentBuffer_decorators; let _contentBuffer_initializers = []; let _contentBuffer_extraInitializers = []; let _base_decorators; let _base_initializers = []; let _base_extraInitializers = []; let _sync_decorators; let _sync_initializers = []; let _sync_extraInitializers = []; return class SmartFile extends _classSuper { static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _path_decorators = [plugins.smartjson.foldDec()]; _contentBuffer_decorators = [plugins.smartjson.foldDec()]; _base_decorators = [plugins.smartjson.foldDec()]; _sync_decorators = [plugins.smartjson.foldDec()]; __esDecorate(this, null, _path_decorators, { kind: "accessor", name: "path", static: false, private: false, access: { has: obj => "path" in obj, get: obj => obj.path, set: (obj, value) => { obj.path = value; } }, metadata: _metadata }, _path_initializers, _path_extraInitializers); __esDecorate(this, null, _contentBuffer_decorators, { kind: "accessor", name: "contentBuffer", static: false, private: false, access: { has: obj => "contentBuffer" in obj, get: obj => obj.contentBuffer, set: (obj, value) => { obj.contentBuffer = value; } }, metadata: _metadata }, _contentBuffer_initializers, _contentBuffer_extraInitializers); __esDecorate(this, null, _base_decorators, { kind: "accessor", name: "base", static: false, private: false, access: { has: obj => "base" in obj, get: obj => obj.base, set: (obj, value) => { obj.base = value; } }, metadata: _metadata }, _base_initializers, _base_extraInitializers); __esDecorate(this, null, _sync_decorators, { kind: "accessor", name: "sync", static: false, private: false, access: { has: obj => "sync" in obj, get: obj => obj.sync, set: (obj, value) => { obj.sync = value; } }, metadata: _metadata }, _sync_initializers, _sync_extraInitializers); if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } // ======== // INSTANCE // ======== /** * Reference to the SmartFs instance for filesystem operations */ smartFs; #path_accessor_storage = __runInitializers(this, _path_initializers, ''); /** * the relative path of the file */ get path() { return this.#path_accessor_storage; } set path(value) { this.#path_accessor_storage = value; } /** * a parsed path */ get parsedPath() { return plugins.path.parse(this.path); } get absolutePath() { return plugins.path.join(this.base, this.path); } get absoluteParsedPath() { return plugins.path.parse(this.absolutePath); } #contentBuffer_accessor_storage = (__runInitializers(this, _path_extraInitializers), __runInitializers(this, _contentBuffer_initializers, Buffer.alloc(0))); /** * the content of the file as Buffer */ get contentBuffer() { return this.#contentBuffer_accessor_storage; } set contentBuffer(value) { this.#contentBuffer_accessor_storage = value; } #base_accessor_storage = (__runInitializers(this, _contentBuffer_extraInitializers), __runInitializers(this, _base_initializers, process.cwd())); /** * The current working directory of the file * Note:this is similar to gulp and different from native node path base */ get base() { return this.#base_accessor_storage; } set base(value) { this.#base_accessor_storage = value; } #sync_accessor_storage = (__runInitializers(this, _base_extraInitializers), __runInitializers(this, _sync_initializers, false)); /** * sync the file with disk */ get sync() { return this.#sync_accessor_storage; } set sync(value) { this.#sync_accessor_storage = value; } /** * the constructor of Smartfile * @param optionsArg * @param smartFs optional SmartFs instance for filesystem operations */ constructor(optionsArg = { path: '', contentBuffer: Buffer.alloc(0), base: process.cwd(), }, smartFs) { super(); __runInitializers(this, _sync_extraInitializers); this.contentBuffer = optionsArg.contentBuffer || Buffer.alloc(0); this.path = optionsArg.path; this.base = optionsArg.base; this.smartFs = smartFs; } /** * set contents from string * @param contentString */ setContentsFromString(contentString, encodingArg = 'utf8') { this.contents = Buffer.from(contentString, encodingArg); } /** * write file to disk at its original location * Behaviours: * - no argument write to exactly where the file was picked up * - Requires SmartFs instance (create via SmartFileFactory) */ async write() { if (!this.smartFs) { throw new Error('No SmartFs instance available. Create SmartFile through SmartFileFactory.'); } const writePath = plugins.smartpath.transform.makeAbsolute(this.path, this.base); console.log(`writing to ${writePath}`); await this.smartFs.file(writePath).write(this.contentBuffer); } /** * writes the file to path given as argument * note: if the path is not absolute, takes process.cwd() as base * @param filePathArg */ async writeToDiskAtPath(filePathArg) { if (!this.smartFs) { throw new Error('No SmartFs instance available. Create SmartFile through SmartFileFactory.'); } if (!plugins.path.isAbsolute(filePathArg)) { filePathArg = plugins.path.join(process.cwd(), filePathArg); } await this.smartFs.file(filePathArg).write(this.contentBuffer); } /** * writes the file to a directory combined with the relative path portion * @param dirPathArg * @returns */ async writeToDir(dirPathArg) { if (!this.smartFs) { throw new Error('No SmartFs instance available. Create SmartFile through SmartFileFactory.'); } dirPathArg = plugins.smartpath.transform.toAbsolute(dirPathArg); const filePath = plugins.path.join(dirPathArg, this.path); await this.smartFs.file(filePath).write(this.contentBuffer); return filePath; } /** * read file from disk */ async read() { if (!this.smartFs) { throw new Error('No SmartFs instance available. Create SmartFile through SmartFileFactory.'); } const filePath = plugins.path.join(this.base, this.path); const content = await this.smartFs.file(filePath).read(); this.contentBuffer = Buffer.from(content); } /** * deletes the file from disk at its original location */ async delete() { if (!this.smartFs) { throw new Error('No SmartFs instance available. Create SmartFile through SmartFileFactory.'); } const filePath = plugins.path.join(this.base, this.path); await this.smartFs.file(filePath).delete(); } /** * Renames the file to the specified new name. * - Updates the `path` property with the new name. * - Writes the file to the new location if it exists on disk. * @param newName The new name of the file (including extension if applicable). * @param writeToDisk (optional) If true, also renames the file on the disk. * @returns The updated file path after renaming. */ async rename(newName, writeToDisk = false) { // Validate the new name if (!newName || typeof newName !== 'string') { throw new Error('Invalid new name provided.'); } // Extract the directory path const oldFilePath = this.path; const dirPath = plugins.path.dirname(this.path); // Create the new file path const newFilePath = plugins.path.join(dirPath, newName); // Update the `path` property this.path = newFilePath; // Optionally write the renamed file to disk if (writeToDisk) { const oldAbsolutePath = plugins.smartpath.transform.makeAbsolute(oldFilePath, this.base); const newAbsolutePath = plugins.smartpath.transform.makeAbsolute(newFilePath, this.base); // Rename the file on disk await plugins.fsPromises.rename(oldAbsolutePath, newAbsolutePath); } // Return the new path return this.path; } // ----------------------------------------------- // vinyl compatibility // ----------------------------------------------- /** * vinyl-compatibility: alias of this.contentBuffer */ get contents() { return this.contentBuffer; } set contents(contentsArg) { this.contentBuffer = contentsArg; } /** * vinyl-compatibility */ get cwd() { return process.cwd(); } /** * return relative path of file */ get relative() { return this.path; } /** * return truw when the file has content */ isNull() { if (!this.contentBuffer) { return true; } return false; } /** * return true if contents are Buffer */ isBuffer() { if (this.contents instanceof Buffer) { return true; } return false; } isDirectory() { return false; } isStream() { return false; } isSymbolic() { return false; } async getHash(typeArg = 'all') { const pathHash = await plugins.smarthash.sha256FromString(this.path); const contentHash = await plugins.smarthash.sha256FromBuffer(this.contentBuffer); const combinedHash = await plugins.smarthash.sha256FromString(pathHash + contentHash); switch (typeArg) { case 'path': return pathHash; case 'content': return contentHash; case 'all': default: return combinedHash; } } // update things updateFileName(fileNameArg) { const oldFileName = this.parsedPath.base; this.path = this.path.replace(new RegExp(oldFileName + '$'), fileNameArg); } async editContentAsString(editFuncArg) { const newFileString = await editFuncArg(this.contentBuffer.toString()); this.contentBuffer = Buffer.from(newFileString); } /** * Returns a ReadableStream from the file's content buffer */ getStream() { const stream = new plugins.stream.Readable(); stream.push(this.contentBuffer); // Push the content buffer to the stream stream.push(null); // Push null to signify the end of the stream (EOF) return stream; } /** * Returns the size of the file in bytes */ async getSize() { return this.contentBuffer.length; } /** * Parse content as string with specified encoding */ parseContentAsString(encodingArg = 'utf8') { return this.contentBuffer.toString(encodingArg); } /** * Parse content as buffer */ parseContentAsBuffer() { return this.contentBuffer; } }; })(); export { SmartFile }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbWFydGZpbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLnNtYXJ0ZmlsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFReEM7OztHQUdHO0lBQ1UsU0FBUztzQkFBUyxPQUFPLENBQUMsU0FBUyxDQUFDLFNBQVM7Ozs7Ozs7Ozs7Ozs7aUJBQTdDLFNBQVUsU0FBUSxXQUEyQjs7O2dDQVl2RCxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRTt5Q0FvQjNCLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFO2dDQU8zQixPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRTtnQ0FNM0IsT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUU7WUFoQzVCLGlLQUFnQixJQUFJLDZCQUFKLElBQUksbUZBQWM7WUFvQmxDLDRMQUFnQixhQUFhLDZCQUFiLGFBQWEscUdBQTJCO1lBT3hELGlLQUFnQixJQUFJLDZCQUFKLElBQUksbUZBQXlCO1lBTTdDLGlLQUFnQixJQUFJLDZCQUFKLElBQUksbUZBQWtCOzs7UUE3Q3RDLFdBQVc7UUFDWCxXQUFXO1FBQ1gsV0FBVztRQUVYOztXQUVHO1FBQ0ssT0FBTyxDQUFPO1FBS3RCLHFFQUErQixFQUFFLEVBQUM7UUFKbEM7O1dBRUc7UUFFSCxJQUFnQixJQUFJLDBDQUFjO1FBQWxDLElBQWdCLElBQUksZ0RBQWM7UUFFbEM7O1dBRUc7UUFDSCxJQUFXLFVBQVU7WUFDbkIsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkMsQ0FBQztRQUNELElBQVcsWUFBWTtZQUNyQixPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFB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