679 lines
12 KiB
JavaScript
679 lines
12 KiB
JavaScript
/*
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|