import { BaseEncodingOptions, exists, lstat } from "fs"; import { mkdir, writeFile } from 'fs/promises'; import { type } from "os"; import { promisify } from "util"; const _exists = promisify(exists); const _lstat = promisify(lstat); /** * Function to create a File * @param fileName Read the File. * @param content content which should be stored * @param options The options to write the file. See original docu: https://nodejs.org/dist/latest-v8.x/docs/api/fs.html#fs_fs_writefile_file_data_options_callback */ export async function createFile(fileName: string, content: string, options?: (BaseEncodingOptions & { mode?: string | number; flag?: string | number; }) | "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex") { // Based on the OS select the Path Element. const SPLITCHAR = type() === 'Linux' ? '/' : '\\'; // Adapt the File Pathes fileName = type() === 'Linux' ? fileName.replace(/\\\\/g, '/') : fileName.replace(/\//g, '\\'); // Split the Path into different segements. const pathParts = fileName.split(SPLITCHAR); // Pop the File. pathParts.pop(); // Create the Path / Directories await createPath(pathParts.join(SPLITCHAR)) // Wirte the File. await writeFile(fileName, content, options) return fileName; } /** * Function to create a File * @param path Read the File. * @param content content which should be stored * @param options The options to write the file. See original docu: https://nodejs.org/dist/latest-v8.x/docs/api/fs.html#fs_fs_writefile_file_data_options_callback */ export async function createPath(path: string) { // Based on the OS select the Path Element. const SPLITCHAR = type() === 'Linux' ? '/' : '\\'; // Adapt the File Pathes path = type() === 'Linux' ? path.replace(/\\\\/g, '/') : path.replace(/\//g, '\\'); // Split the Path into different segements. const pathParts = path.split('/'); if (pathParts.length > 0) { /** Check if the given Path Ends with a File Name */ if (pathParts[pathParts.length - 1].indexOf('.') !== -1) { pathParts.pop(); } // Reassemble the Segments like that: // // C:\\Test\\SubFolder\\AnotherFolder // Split up: // => fileParts = [C: , Test , SubFolder, AnotherFolder] // // Reassemble: // 1) C: // 2) C:\\Test // 3) C:\\Test\\SubFolder // 4) ... // // Everytime after an assembly Check whether the assembled // path exists, otherwise create that folder and go on. for (const [idx, folder] of pathParts.entries()) { // Assemble the Path. const currentPath = pathParts.slice(0, idx + 1).join(SPLITCHAR); // Test and create the Folder const urlExists = await _exists(currentPath); // Test if the provided Path exists or not. if (currentPath && !urlExists) { await mkdir(currentPath); } else if (currentPath && urlExists && (await _lstat(currentPath)).isFile()) { throw Error('Cant create File at the specified path. The given URL contains a File. See "' + currentPath + '"'); } } } return path; }