/** * Transaction builder for atomic multi-file operations */ import type { ISmartFsProvider } from '../interfaces/mod.provider.js'; import type { ITransactionOperation, TEncoding } from '../interfaces/mod.types.js'; /** * Transaction file operation builder * Allows chaining file operations within a transaction */ class TransactionFileBuilder { constructor( private transaction: SmartFsTransaction, private path: string, ) {} /** * Write content to the file in this transaction * @param content - Content to write * @param encoding - Optional encoding */ public write(content: string | Buffer, encoding?: TEncoding): SmartFsTransaction { this.transaction.addOperation({ type: 'write', path: this.path, content, encoding, }); return this.transaction; } /** * Append content to the file in this transaction * @param content - Content to append * @param encoding - Optional encoding */ public append(content: string | Buffer, encoding?: TEncoding): SmartFsTransaction { this.transaction.addOperation({ type: 'append', path: this.path, content, encoding, }); return this.transaction; } /** * Delete the file in this transaction */ public delete(): SmartFsTransaction { this.transaction.addOperation({ type: 'delete', path: this.path, }); return this.transaction; } /** * Copy the file to a new location in this transaction * @param targetPath - Destination path */ public copy(targetPath: string): SmartFsTransaction { this.transaction.addOperation({ type: 'copy', path: this.path, targetPath, }); return this.transaction; } /** * Move the file to a new location in this transaction * @param targetPath - Destination path */ public move(targetPath: string): SmartFsTransaction { this.transaction.addOperation({ type: 'move', path: this.path, targetPath, }); return this.transaction; } } /** * Transaction builder class for atomic multi-file operations * Build up a set of operations, then commit atomically * Supports rollback on failure */ export class SmartFsTransaction { private provider: ISmartFsProvider; private operations: ITransactionOperation[] = []; private committed = false; private rolledBack = false; constructor(provider: ISmartFsProvider) { this.provider = provider; } /** * Add a file operation to the transaction * @param path - Path to the file * @returns TransactionFileBuilder for chaining operations * * @example * ```typescript * await fs.transaction() * .file('/file1.txt').write('content1') * .file('/file2.txt').delete() * .commit() * ``` */ public file(path: string): TransactionFileBuilder { const normalizedPath = this.provider.normalizePath(path); return new TransactionFileBuilder(this, normalizedPath); } /** * Add an operation to the transaction (internal) */ public addOperation(operation: ITransactionOperation): void { if (this.committed) { throw new Error('Cannot add operations to a committed transaction'); } if (this.rolledBack) { throw new Error('Cannot add operations to a rolled back transaction'); } this.operations.push(operation); } /** * Commit the transaction * All operations are executed atomically * If any operation fails, all operations are rolled back */ public async commit(): Promise { if (this.committed) { throw new Error('Transaction already committed'); } if (this.rolledBack) { throw new Error('Cannot commit a rolled back transaction'); } if (this.operations.length === 0) { this.committed = true; return; } try { // Prepare transaction (create backups for rollback) const preparedOperations = await this.provider.prepareTransaction(this.operations); this.operations = preparedOperations; // Execute the transaction await this.provider.executeTransaction(this.operations); this.committed = true; } catch (error) { // Rollback on error await this.rollback(); throw error; } } /** * Rollback the transaction * Reverts all operations that have been executed */ public async rollback(): Promise { if (this.committed) { throw new Error('Cannot rollback a committed transaction'); } if (this.rolledBack) { throw new Error('Transaction already rolled back'); } if (this.operations.length === 0) { this.rolledBack = true; return; } await this.provider.rollbackTransaction(this.operations); this.rolledBack = true; } /** * Get all operations in the transaction */ public getOperations(): readonly ITransactionOperation[] { return this.operations; } /** * Check if the transaction has been committed */ public isCommitted(): boolean { return this.committed; } /** * Check if the transaction has been rolled back */ public isRolledBack(): boolean { return this.rolledBack; } }