First commit
This commit is contained in:
678
framework/server/filemanager.js
Normal file
678
framework/server/filemanager.js
Normal file
@@ -0,0 +1,678 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2020, 2023, The Unified Company.
|
||||
|
||||
This code is part of Unify.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the ESA Software Community License - Strong Copyleft LICENSE,
|
||||
as published by the ESA.
|
||||
See the ESA Software Community License - Strong Copyleft LICENSE, for more details.
|
||||
|
||||
https://unifyjs.org
|
||||
|
||||
*/
|
||||
|
||||
import file from './file.js';
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import fse from "fs-extra";
|
||||
|
||||
import tools from '../unify/tools.js';
|
||||
|
||||
import multiExtender from './multiExtender.js';
|
||||
|
||||
import objectParser from './objectParser.js';
|
||||
|
||||
import cacheDisabler from './cacheDisabler.js';
|
||||
|
||||
|
||||
export default class filemanager{
|
||||
|
||||
applications = new Array();
|
||||
|
||||
files = new Array();
|
||||
|
||||
directories = new Array();
|
||||
|
||||
replacements = new Array();
|
||||
|
||||
cores = new Array();
|
||||
|
||||
pragmas = new Array();
|
||||
|
||||
allFiles = new Array();
|
||||
|
||||
|
||||
storeSource = true;
|
||||
|
||||
cache_folder_depth = 0;
|
||||
|
||||
|
||||
multiExtender = new multiExtender();
|
||||
|
||||
objectParser = new objectParser();
|
||||
|
||||
cacheDisabler = new cacheDisabler();
|
||||
|
||||
|
||||
crossPlatformPath( path ) {
|
||||
|
||||
return tools.slash( path );
|
||||
|
||||
}
|
||||
|
||||
constructor( cache_directory ) {
|
||||
|
||||
if( !cache_directory ) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
this.cache_directory = this.crossPlatformPath( cache_directory );
|
||||
|
||||
this.writeRandomString()
|
||||
|
||||
}
|
||||
|
||||
async writeRandomString() {
|
||||
|
||||
this.randomString = String(Math.floor(Math.random() * 1000 )).padStart(4, '0');
|
||||
|
||||
this.cacheDisabler.randomString = this.randomString;
|
||||
|
||||
await fs.writeFileSync( "./framework/configs/randomString.json", this.randomString );
|
||||
|
||||
}
|
||||
|
||||
routeDirectory( directory, relativeDirectory ) {
|
||||
|
||||
var path = "framework";
|
||||
|
||||
var subPath = "unify";
|
||||
|
||||
var files = fs.readdirSync( directory );
|
||||
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
|
||||
var fileName = files[i];
|
||||
|
||||
var fileLocation = relativeDirectory + fileName;
|
||||
|
||||
this.replace( fileLocation );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
addCustomReplacements() {
|
||||
|
||||
this.addReplacement( "/elements/", "/"+this.cache_directory+"elements/");
|
||||
|
||||
this.addReplacement( "/user/", "/"+this.cache_directory+"user/" );
|
||||
|
||||
this.replace( "/engine/");
|
||||
|
||||
this.replace( "/3rdparty/");
|
||||
|
||||
this.routeDirectory( "framework/unify", "/unify/" );
|
||||
|
||||
this.routeDirectory( "framework/server", "/server/" );
|
||||
|
||||
this.routeDirectory( "framework/client", "/client/" );
|
||||
|
||||
this.routeDirectory( "framework/unify/sql", "/unify/sql/" );
|
||||
|
||||
this.routeDirectory( "framework/unify/math", "/unify/math/" );
|
||||
|
||||
}
|
||||
|
||||
replace( source ) {
|
||||
|
||||
var target = "/framework" + source;
|
||||
|
||||
this.addReplacement(source, target);
|
||||
|
||||
}
|
||||
|
||||
addReplacement( source, target ) {
|
||||
|
||||
var replacement = new Object();
|
||||
|
||||
replacement.source = source;
|
||||
|
||||
replacement.target = target;
|
||||
|
||||
this.replacements.push( replacement );
|
||||
|
||||
}
|
||||
|
||||
readFileListCache( filesJson ) {
|
||||
|
||||
this.files = filesJson;
|
||||
|
||||
}
|
||||
|
||||
getFiles() {
|
||||
|
||||
return this.files;
|
||||
|
||||
}
|
||||
|
||||
writeFileListCache() {
|
||||
|
||||
var json = "export default " + JSON.stringify( this.files ) + ";";
|
||||
|
||||
fs.writeFileSync( "./framework/configs/files.js", json );
|
||||
|
||||
|
||||
var json = "export default " + JSON.stringify( this.applications ) + ";";
|
||||
|
||||
fs.writeFileSync( "./framework/configs/applications.js", json );
|
||||
|
||||
}
|
||||
|
||||
async updateCache() {
|
||||
|
||||
await this.findApplicationFiles( "./application");
|
||||
|
||||
await this.emptyCacheDirectory();
|
||||
|
||||
await this.createDirectories();
|
||||
|
||||
await this.writeFiles();
|
||||
|
||||
}
|
||||
|
||||
addReplacement( source, target ) {
|
||||
|
||||
var replacement = new Object();
|
||||
|
||||
replacement.source = source;
|
||||
|
||||
replacement.target = target;
|
||||
|
||||
this.replacements.push( replacement );
|
||||
|
||||
}
|
||||
|
||||
async createDir( path ) {
|
||||
|
||||
fse.ensureDirSync( path );
|
||||
|
||||
}
|
||||
|
||||
async emptyCacheDirectory() {
|
||||
|
||||
fs.emptyDirSync( this.cache_directory );
|
||||
|
||||
}
|
||||
|
||||
async createDirectory( directory ) {
|
||||
|
||||
if( this.temporary_cache_directory ) {
|
||||
|
||||
//console.log(path.resolve( this.temporary_cache_directory + directory ));
|
||||
|
||||
fs.ensureDirSync( path.resolve( this.temporary_cache_directory + directory ) );
|
||||
|
||||
} else {
|
||||
|
||||
fs.ensureDirSync( path.resolve( this.cache_directory + directory ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async createDirectories() {
|
||||
|
||||
var directories = this.directories.reverse();
|
||||
|
||||
for( var c = 0; c < directories.length; c++ ) {
|
||||
|
||||
var directory = directories[c];
|
||||
|
||||
this.createDirectory( directory );
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
definePragma( pragma ) {
|
||||
|
||||
this.pragmas.push( pragma );
|
||||
|
||||
}
|
||||
|
||||
cleanURL( source ) {
|
||||
|
||||
var token = "//";
|
||||
|
||||
for ( var i = 0; i < 4; i++ ) {
|
||||
|
||||
token += "/";
|
||||
|
||||
source = source.replaceAll( token, "/" );
|
||||
|
||||
}
|
||||
|
||||
source = source.replaceAll('..//', '../');
|
||||
|
||||
return source;
|
||||
|
||||
}
|
||||
|
||||
definePragmas( source ) {
|
||||
|
||||
for ( var i = 0; i < this.pragmas.length; i++ ) {
|
||||
|
||||
var pragma = this.pragmas[i];
|
||||
|
||||
source = "\n\n#define " + pragma.toUpperCase() + " \n\n" + source;
|
||||
|
||||
}
|
||||
|
||||
return source;
|
||||
|
||||
}
|
||||
|
||||
writeFileToDisk( source, path, filename ) {
|
||||
|
||||
if( this.temporary_cache_directory ) {
|
||||
|
||||
fs.writeFileSync( this.temporary_cache_directory + path + "/" + filename, source );
|
||||
|
||||
} else {
|
||||
|
||||
fs.writeFileSync( this.cache_directory + path + "/" + filename, source );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
composeFile( file, side ) {
|
||||
|
||||
var path = file.path;
|
||||
|
||||
var filename = file.name;
|
||||
|
||||
var source = file.parsedSource;
|
||||
|
||||
var customMethodPreFixes = new Array("node", "state");
|
||||
|
||||
if( source ) {
|
||||
|
||||
source = this.cleanURL( source );
|
||||
|
||||
source = this.objectParser.compose( source, path + "/" + filename, customMethodPreFixes );
|
||||
|
||||
if( side == "client" ) {
|
||||
|
||||
source = this.cacheDisabler.parseSource( source, path + "/" + filename );
|
||||
|
||||
}
|
||||
|
||||
source = this.multiExtender.enableMultiExtend( source, file.depth );
|
||||
|
||||
source = this.definePragmas( source );
|
||||
|
||||
this.writeFileToDisk( source, path, filename );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async writeFiles( side ) {
|
||||
|
||||
var files = this.files;
|
||||
|
||||
for( var c = 0; c < files.length; c++ ) {
|
||||
|
||||
var file = files[c];
|
||||
|
||||
this.composeFile( file, side );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async renewCache( directory, files ) {
|
||||
|
||||
for( var c = 0; c < files.length; c++ ) {
|
||||
|
||||
var filename = files[c];
|
||||
|
||||
var filePath = this.cache_directory + "/" + filename;
|
||||
|
||||
console.log( "Refresh cache:", directory, filename );
|
||||
|
||||
filePath = path.resolve( filePath )
|
||||
|
||||
var source = await fs.readFileSync( filePath, 'utf8');
|
||||
|
||||
source = this.cacheDisabler.parseSource( source );
|
||||
|
||||
await fs.writeFileSync( filePath, source );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async findApplicationFiles( directory, depth = 0, parentFile ) {
|
||||
|
||||
var files = await fs.readdirSync( directory );
|
||||
|
||||
for( var c = 0; c<files.length; c++ ) {
|
||||
|
||||
var filename = files[c];
|
||||
|
||||
if( filename != ".DS_Store" ) {
|
||||
|
||||
var newFile = await this.processFile( filename, directory, depth, parentFile );
|
||||
|
||||
if( parentFile ) {
|
||||
|
||||
parentFile.add( newFile );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return parentFile;
|
||||
|
||||
}
|
||||
|
||||
normalizePath( directory ) {
|
||||
|
||||
if( process.platform == "win32" ) {
|
||||
|
||||
var separator = "\\";
|
||||
|
||||
} else {
|
||||
|
||||
var separator = "/";
|
||||
|
||||
}
|
||||
|
||||
var dirParts = directory.split( separator );
|
||||
|
||||
dirParts.shift();
|
||||
|
||||
return dirParts.join( separator );
|
||||
|
||||
}
|
||||
|
||||
writeCacheHistory() {
|
||||
|
||||
fs.writeFileSync( path.resolve("./framework/cache/platforms/cachedFiles.json"), JSON.stringify( this.allFiles ) );
|
||||
|
||||
}
|
||||
|
||||
filterFile( file, previousFiles, index ) {
|
||||
|
||||
var name = file.name;
|
||||
|
||||
var searchIndex = previousFiles.findIndex( ( file ) => file.name == name );
|
||||
|
||||
if( searchIndex != -1 ) {
|
||||
|
||||
var previousFile = previousFiles[ searchIndex ];
|
||||
|
||||
if( previousFile.dateModified.toString() == file.dateModified.toString() ) {
|
||||
|
||||
delete this.files[ index ]
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
filterFiles( source ) {
|
||||
|
||||
var previousFiles = JSON.parse( source );
|
||||
|
||||
var files = this.files;
|
||||
|
||||
for ( var index = 0; index < files.length; index++ ) {
|
||||
|
||||
var file = files[ index ];
|
||||
|
||||
this.filterFile( file, previousFiles, index )
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
filterModified() {
|
||||
|
||||
if( !fs.existsSync( path.resolve("./framework/cache/platforms/cachedFiles.json") ) ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var source = fs.readFileSync( path.resolve("./framework/cache/platforms/cachedFiles.json"), "utf8" );
|
||||
|
||||
if( !source ) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
this.filterFiles( source );
|
||||
|
||||
this.files = this.files.filter( n => n );
|
||||
|
||||
}
|
||||
|
||||
getFileType( stats ) {
|
||||
|
||||
if( stats.isDirectory() ) {
|
||||
|
||||
return "directory";
|
||||
|
||||
}
|
||||
|
||||
if( stats.isFile() ) {
|
||||
|
||||
return "file";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
createFileObject( directory, filename, depth ) {
|
||||
|
||||
var filePath = path.join( directory, filename );
|
||||
|
||||
var stats = fs.statSync( filePath );
|
||||
|
||||
|
||||
var newFile = new file();
|
||||
|
||||
newFile.name = filename;
|
||||
|
||||
newFile.path = this.normalizePath( directory );
|
||||
|
||||
newFile.filePath = filePath;
|
||||
|
||||
newFile.depth = depth;
|
||||
|
||||
newFile.dateModified = stats.ctime.toString();
|
||||
|
||||
newFile.type = this.getFileType( stats );
|
||||
|
||||
|
||||
return newFile;
|
||||
|
||||
}
|
||||
|
||||
async processDirectory( newFile, parentFile ) {
|
||||
|
||||
const excludeDirectorys = new Array("assets", ".DS_Store");
|
||||
|
||||
if( !excludeDirectorys.includes( newFile.name ) ) {
|
||||
|
||||
if( parentFile ) {
|
||||
|
||||
await this.findApplicationFiles( newFile.filePath, newFile.depth + 1, newFile );
|
||||
|
||||
} else {
|
||||
|
||||
await this.findApplicationFiles( newFile.filePath, newFile.depth + 1 );
|
||||
|
||||
this.directories.push( this.normalizePath( newFile.filePath ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async processNormalFile( newFile, directory, parentFile ) {
|
||||
|
||||
if( newFile.name == "application.js" ) {
|
||||
|
||||
if( !parentFile ) {
|
||||
|
||||
var fileThree = await this.findApplicationFiles( directory, newFile.depth + 1, newFile );
|
||||
|
||||
this.applications.push( fileThree );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if( this.storeSource ) {
|
||||
|
||||
this.processSource( newFile, newFile.filePath, newFile.depth );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async handleFile( newFile, parentFile, directory ) {
|
||||
|
||||
var fileParts = newFile.name.split(".");
|
||||
|
||||
if( newFile.type == "directory" ) {
|
||||
|
||||
await this.processDirectory( newFile, parentFile );
|
||||
|
||||
} else {
|
||||
|
||||
await this.processNormalFile( newFile, directory, parentFile );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async processFile( filename, directory, depth, parentFile = false ) {
|
||||
|
||||
var newFile = this.createFileObject( directory, filename, depth );
|
||||
|
||||
await this.handleFile( newFile, parentFile, directory, depth );
|
||||
|
||||
|
||||
if( !parentFile ) {
|
||||
|
||||
this.files.push( newFile );
|
||||
|
||||
this.allFiles.push( newFile )
|
||||
|
||||
}
|
||||
|
||||
return newFile;
|
||||
|
||||
}
|
||||
|
||||
async processSource( newFile, filePath, depth ) {
|
||||
|
||||
newFile.source = await fs.readFileSync( filePath, 'utf8' );
|
||||
|
||||
var source = this.cleanURL( newFile.source );
|
||||
|
||||
newFile.source = source;
|
||||
|
||||
newFile.parsedSource = this.parseSource( source , depth );
|
||||
|
||||
return file;
|
||||
|
||||
}
|
||||
|
||||
parseSourceLine( code, replacement, depth ) {
|
||||
|
||||
var source = replacement.source;
|
||||
|
||||
var target = replacement.target;
|
||||
|
||||
|
||||
var relativeTarget = this.computeRelativePath( depth ) + target;
|
||||
|
||||
|
||||
code = code.replaceAll( '"' + source, '"' + relativeTarget );
|
||||
|
||||
code = code.replaceAll( "'" + source, "'" + relativeTarget );
|
||||
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
parseSource( code, depth ) {
|
||||
|
||||
code = "\n\nimport extender from '/unify/extender.js';\n\n " + code;
|
||||
|
||||
var replacements = this.replacements;
|
||||
|
||||
for( var c = 0; c < replacements.length;c++ ) {
|
||||
|
||||
var replacement = replacements[c];
|
||||
|
||||
|
||||
code = this.parseSourceLine( code, replacement, depth );
|
||||
|
||||
}
|
||||
|
||||
code = this.cleanURL( code );
|
||||
|
||||
return code;
|
||||
|
||||
}
|
||||
|
||||
computeRelativePath( depth ){
|
||||
|
||||
var backString = "";
|
||||
|
||||
var path = this.cache_directory;
|
||||
|
||||
var parts = path.split("/")
|
||||
|
||||
parts = parts.filter(n => n)
|
||||
|
||||
|
||||
if( parts[0] == "." ) {
|
||||
|
||||
parts.shift();
|
||||
|
||||
}
|
||||
|
||||
var totalDepth = parts.length + depth;
|
||||
|
||||
for (var i = 0; i < totalDepth; i++) {
|
||||
|
||||
backString += "../";
|
||||
|
||||
}
|
||||
|
||||
return backString;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user