All files / src/libs FileManager.ts

0% Statements 0/52
0% Branches 0/84
0% Functions 0/6
0% Lines 0/52

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221                                                                                                                                                                                                                                                                                                                                                                                                                                                         
import { TFile } from 'obsidian';
import { Logging } from 'src/classes/Logging';
import { Path } from 'src/classes/Path';
import { IApp } from 'src/interfaces/IApp';
import { ILogger, ILogger_ } from 'src/interfaces/ILogger';
import { Resolve } from './DependencyInjection/functions/Resolve';
 
/**
 * A class that handles file operations.
 * Capsulates the Obsidian file operations functions.
 */
export default class FileManager {
    /**
     * Renames a file.
     * @param file The file to rename.
     * @param filename The new filename. If no extension is provided, the extension of the file is used.
     * @param awaitPromise A promise that resolves when the previous changes are written to the file.
     * @returns - true: Whether the renaming was successful or unnecessary (if the filename is already correct).
     * - false: Whether the renaming failed.
     * @remarks - This function will not rename the file if the filename is already correct.
     * - This function use `fileManager.renameFile` to rename the file. Linking will be updated automatically.
     */
    public static async renameFile(
        file: TFile,
        filename: Filename,
        awaitPromise?: Promise<void>,
    ): Promise<boolean> {
        const logger = Logging.getLogger('FileManager/renameFile');
 
        Iif (!file?.parent?.path || !filename) {
            filename ?? logger.error('No new filename provided');
            file ?? logger.error('No file provided');
            file.parent?.path ?? logger.error('No parent path provided');
 
            return false;
        }
 
        Iif (awaitPromise) {
            logger.trace('Waiting for previous promise to resolve');
            await awaitPromise;
        }
 
        const newFilename = new Filename(
            filename.basename,
            filename.extension ?? file.extension,
        );
 
        Iif (
            file.basename === filename.basename &&
            file.extension === filename.extension
        ) {
            logger.debug('Filename is already correct');
 
            return true;
        }
 
        const movePath = Path.join(
            file.parent.path,
            Path.sanitizeFilename(newFilename.filename),
        );
 
        return await this.moveRenameFile(file, movePath, newFilename, logger);
    }
 
    /**
     * Moves a file.
     * @param file The file to move.
     * @param path The new path of the file.
     * @param filename The new filename.
     * @param awaitPromise A promise that resolves when the previous changes are written to the file.
     * @returns - true: Whether the moving was successful.
     * - false: Whether the moving failed.
     */
    public static async moveFile(
        file: TFile,
        path: string,
        filename?: Filename,
        awaitPromise?: Promise<void>,
    ): Promise<boolean> {
        const logger = Logging.getLogger('FileManager/moveFile');
 
        Iif (!file) {
            file ?? logger.error('No file provided');
 
            return false;
        }
 
        Iif (awaitPromise) {
            logger.trace('Waiting for previous promise to resolve');
            await awaitPromise;
        }
 
        const newFilename = new Filename(
            filename?.basename ?? file.basename,
            filename?.extension ?? file.extension,
        );
 
        const movePath = Path.join(
            path,
            Path.sanitizeFilename(newFilename.filename),
        );
 
        return await this.moveRenameFile(file, movePath, newFilename, logger);
    }
 
    /**
     * Moves and renames a file.
     * @param file The file to move and rename.
     * @param path The new path of the file.
     * @param filename The new filename.
     * @param logger A logger to log the process.
     * @returns - true: Whether the moving and renaming was successful.
     * - false: Whether the moving and renaming failed.
     */
    private static async moveRenameFile(
        file: TFile,
        path: string,
        filename: Filename,
        logger?: ILogger,
    ): Promise<boolean> {
        Iif (path === file.path) {
            logger?.debug(
                `Moving/renaming file ${file.name} to ${path} is unnecessary`,
            );
 
            return true;
        }
 
        logger?.trace(`Moving/renaming file ${file.name} to ${path}`);
 
        try {
            await Resolve<IApp>('IApp').fileManager.renameFile(file, path);
        } catch (error) {
            logger?.error(
                `Moving/renaming file ${file.name} to ${path} failed: `,
                error,
            );
 
            return false;
        }
 
        logger?.debug(`Moved/renamed file ${file.name} to ${path} in ${path}`);
 
        return true;
    }
 
    /**
     * Creates a new file.
     * @param path The path of the new file.
     * @param filename The filename of the new file.
     * @param content The content of the new file.
     * @returns - The new file if successful.
     * - undefined if the creation failed.
     */
    public static async createFile(
        path: string,
        filename: Filename,
        content?: string,
    ): Promise<TFile | undefined> {
        const logger = Resolve<ILogger_>('ILogger_').getLogger(
            'FileManager/createFile',
        );
 
        const newFilename = new Filename(
            filename.basename,
            filename.extension ?? 'md',
        );
 
        const filePath = Path.join(
            path,
            Path.sanitizeFilename(newFilename.filename),
        );
 
        try {
            const file = await Resolve<IApp>('IApp').vault.create(
                filePath,
                content ?? '',
            );
 
            logger.debug(`Created file ${file.name} in ${path}`);
 
            return file;
        } catch (error) {
            logger.error(`Creating file ${filePath} failed: `, error);
 
            return undefined;
        }
    }
}
 
/**
 * A filename with basename and extension.
 */
export class Filename {
    /**
     * The basename of the filename.
     */
    public basename: string;
    /**
     * The extension of the filename.
     */
    public extension: string | undefined;
 
    /**
     * The full filename.
     */
    get filename(): string {
        return `${this.basename}${this.extension ? `.${this.extension}` : ''}`;
    }
 
    /**
     * Creates a new filename.
     * @param basename The basename of the filename.
     * @param extension The extension of the filename.
     */
    constructor(basename: string, extension?: string) {
        this.basename = basename;
        this.extension = extension;
    }
}
 
Zur TypeDoc-Dokumentation