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