library-ts/node/files/Files.ts

373 lines
7.7 KiB
TypeScript
Raw Normal View History

2025-03-31 12:00:55 +00:00
import { promises as fs } from "fs";
import * as path from "path";
import { RJLog } from "../log/RJLog";
import { PathReference } from "./PathReference";
import { DOMShim } from "../DOMShim";
import { DateMath } from "../../browser/date/DateMath";
export class Files
{
static parentPath( filePath:string )
{
return path.dirname( filePath );
}
static async forAllIn( filePath:string, filter:(p:PathReference)=>Promise<boolean> = null, action:(p:PathReference)=>Promise<void> = null ):Promise<PathReference[]>
{
let files = await fs.readdir( filePath );
let root = new PathReference( filePath );
let pathReferences = files.map( f => root.createRelative( f ) );
if ( filter )
{
let filteredPaths = [];
for ( let p of pathReferences )
{
if ( await filter( p ) )
{
filteredPaths.push( p );
}
}
pathReferences = filteredPaths;
};
for ( let p of pathReferences )
{
let isDirectory = await p.isDirectory();
if ( isDirectory )
{
await this.forAllIn( p.absolutePath, filter, action );
}
}
if ( action )
{
for ( let p of pathReferences )
{
await action( p );
}
}
return Promise.resolve( pathReferences );
}
static async forDirectChildrenIn( filePath:string, filter:(p:PathReference)=>Promise<boolean> = null, action:(p:PathReference)=>Promise<void> = null ):Promise<PathReference[]>
{
let files = await fs.readdir( filePath );
let root = new PathReference( filePath );
let pathReferences = files.map( f => root.createRelative( f ) );
if ( filter )
{
let filteredPaths = [];
for ( let p of pathReferences )
{
if ( await filter( p ) )
{
filteredPaths.push( p );
}
}
pathReferences = filteredPaths;
};
if ( action )
{
for ( let p of pathReferences )
{
await action( p );
}
}
return Promise.resolve( pathReferences );
}
static joinPaths( pathFragments:string[] )
{
return path.join.apply( path, pathFragments );
}
static async existsIn( directoryPath:string, fileName:string ):Promise<boolean>
{
let combinedPath = Files.joinPaths( [ directoryPath, fileName ] );
let result = await Files.exists( combinedPath );
return Promise.resolve( result );
}
static async getStatistics( filePath:string )
{
return fs.stat( filePath );
}
static async getModificationDate( filePath:string ):Promise<Date>
{
let stats = await this.getStatistics( filePath );
if ( ! stats )
{
return Promise.resolve( null );
}
return new Date( stats.mtimeMs );
}
static async isNewerThan( filePath:string, date:Date ):Promise<boolean>
{
let mDate = await this.getModificationDate( filePath );
return Promise.resolve( DateMath.isAfter( mDate, date ) );
}
static async isDirectory( filePath:string ):Promise<boolean>
{
try
{
let stats = await fs.stat( filePath );
return Promise.resolve( stats !== null && stats !== undefined && stats.isDirectory() );
}
catch( e )
{
return false;
}
return Promise.resolve( false );
}
static async isFile( filePath:string ):Promise<boolean>
{
try
{
let stats = await fs.stat( filePath );
return Promise.resolve( stats !== null && stats !== undefined && stats.isFile() );
}
catch( e )
{
return false;
}
return Promise.resolve( false );
}
static async isSymbolicLink( filePath:string ):Promise<boolean>
{
try
{
let stats = await fs.stat( filePath );
return Promise.resolve( stats !== null && stats !== undefined && stats.isSymbolicLink() );
}
catch( e )
{
return false;
}
return Promise.resolve( false );
}
static async exists( filePath:string ):Promise<boolean>
{
try
{
let stats = await fs.stat( filePath );
return Promise.resolve( stats !== null && stats !== undefined );
}
catch( e )
{
return false;
}
return Promise.resolve( false );
}
static async ensureDirectoryExists( path:string ):Promise<void>
{
let exists = await Files.exists( path );
if ( exists )
{
return Promise.resolve();
}
await fs.mkdir( path, { recursive: true } );
return Promise.resolve();
}
static async ensureParentDirectoryExists( filePath:string ):Promise<void>
{
let path = Files.parentPath( filePath );
let exists = await Files.exists( path );
if ( exists )
{
return Promise.resolve();
}
await fs.mkdir( path );
return Promise.resolve();
}
static async deleteFile( filePath:string ):Promise<boolean>
{
try
{
await fs.unlink( filePath );
}
catch( e )
{
return Promise.resolve( false );
}
return Promise.resolve( true );
}
static async loadUTF8( filePath:string ):Promise<string>
{
try
{
let data = await fs.readFile( filePath );
let stringData = data.toString();
return Promise.resolve( stringData );
}
catch ( exception )
{
RJLog.log( exception );
}
return Promise.resolve( null );
}
static async moveFile( oldPath:string, newPath:string )
{
try
{
await fs.rename( oldPath, newPath );
}
catch ( e )
{
await fs.copyFile( oldPath, newPath );
await fs.unlink( oldPath );
}
}
static async loadJSON<T>( filePath:string ):Promise<T>
{
let text = await Files.loadUTF8( filePath );
if ( text === null )
{
return Promise.resolve( null );
}
try
{
let jsonObject = JSON.parse( text );
return Promise.resolve( jsonObject as T );
}
catch ( exception )
{
RJLog.log( exception );
}
return Promise.resolve( null );
}
static async saveUTF8( filePath:string, text:string ):Promise<boolean>
{
try
{
await fs.writeFile( filePath, text );
return Promise.resolve( true );
}
catch ( exception )
{
RJLog.log( exception );
}
return Promise.resolve( false );
}
static async saveJSON<T>( filePath:string, data:T ):Promise<boolean>
{
try
{
let jsonData = JSON.stringify( data );
let result = await Files.saveUTF8( filePath, jsonData );
return Promise.resolve( result );
}
catch( e )
{
RJLog.log( e );
}
return Promise.resolve( false );
}
static async saveXML( filePath:string, rootElement:Element ):Promise<void>
{
let domShim = DOMShim.$;
let nodeName = rootElement.nodeName;
let xmlHeader = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>` + "\n";
let serializedXML = `${xmlHeader}<${nodeName}>${rootElement.innerHTML}</${nodeName}>` ;
//RJLog.log( rootElement, serializedXML );
await Files.saveUTF8( filePath, serializedXML );
return Promise.resolve();
}
static async loadXML( filePath:string ):Promise<Document>
{
let domShim = DOMShim.$;
let stringData = await Files.loadUTF8( filePath );
let parser = new DOMParser();
let xmlDoc = parser.parseFromString( stringData, "text/xml" );
return xmlDoc;
}
static async loadHTML( filePath:string ):Promise<Document>
{
let domShim = DOMShim.$;
let stringData = await Files.loadUTF8( filePath );
let parser = new DOMParser();
let xmlDoc = parser.parseFromString( stringData, "text/html" );
return xmlDoc;
}
static async saveHTML( filePath:string, rootElement:Element ):Promise<void>
{
let domShim = DOMShim.$;
await Files.saveUTF8( filePath, rootElement.outerHTML );
return Promise.resolve();
}
}