116 lines
4.0 KiB
JavaScript
116 lines
4.0 KiB
JavaScript
class FakeFileSystem {
|
|
|
|
constructor() {
|
|
this.currentPath='/'
|
|
this.path2dir = {}
|
|
}
|
|
|
|
/*
|
|
loadStructure : loads an object like dirname: [ subojbects ]
|
|
*/
|
|
loadStructure(struct, files) {
|
|
this._scanStruct('/', struct, files || []);
|
|
}
|
|
|
|
_scanStruct(locPath, struct, files){
|
|
this.path2dir[locPath]={ /* assign local files & local folers*/
|
|
files: [...files.filter(item=>{
|
|
let filePath = (item.fullPath.split('/').length>2) ? item.fullPath.substr(0,item.fullPath.lastIndexOf('/')) : '/'
|
|
return(filePath==locPath)
|
|
})],
|
|
folders: [...Object.keys(struct).map(item=> {
|
|
let folderPath = (locPath=='/') ? '/'+item: locPath+'/'+item
|
|
let childrenFiles = files.filter(item=>(item.object.path==folderPath))
|
|
return({
|
|
name:item,
|
|
path: folderPath,
|
|
isEmpty:( (Object.keys(struct[item]).length==0) && (childrenFiles.length==0) )
|
|
})
|
|
})]
|
|
}
|
|
if(locPath!='/') this.path2dir[locPath].folders.unshift({name:'..', path:'..'})
|
|
|
|
this.path2dir[locPath].files.sort((a,b)=>((a.object.name<b.object.name) ? -1 : 1))
|
|
this.path2dir[locPath].folders.sort((a,b)=>((a.name<b.name) ? -1 : 1))
|
|
for(let folderName of Object.keys(struct)){ // Now recur for each subfolder
|
|
let subPath = (locPath=='/') ? '/'+folderName : locPath+'/'+folderName
|
|
let childrenFiles = files.filter(item=>(item.fullPath.length>subPath.length))
|
|
this._scanStruct(
|
|
subPath,
|
|
struct[folderName],
|
|
childrenFiles
|
|
)
|
|
}
|
|
}
|
|
|
|
/*
|
|
getFolder : returns an alphabetically sorted array of folders at the current path
|
|
*/
|
|
getFolders(){
|
|
return(this.path2dir[this.currentPath].folders)
|
|
}
|
|
|
|
/*
|
|
getFiles : returns an alphabetically sorted array of files at the current path
|
|
*/
|
|
getFiles(){
|
|
return(this.path2dir[this.currentPath].files)
|
|
}
|
|
|
|
/*
|
|
findFile : returns the path of the first file than validates the comparison function.
|
|
The comparison function is given the file object as parameter, and should return a boolean.
|
|
*/
|
|
findFile(fn){
|
|
for(let path of Object.keys(this.path2dir)){
|
|
for(let file of this.path2dir[path].files){
|
|
if(fn(file.object)) return(path)
|
|
}
|
|
}
|
|
return(false)
|
|
}
|
|
|
|
/*
|
|
changeDir : changes the current path, relatively or absolutely
|
|
*/
|
|
changeDir(path){
|
|
if(path.startsWith('/')){ //Absolute
|
|
if(this.pathExists(path)) this.currentPath = path
|
|
} else { //relative
|
|
let newPath = this.normalizePath(this.currentPath+'/'+path)
|
|
if(newPath=='') newPath='/'
|
|
if(this.pathExists(newPath)) this.currentPath = newPath
|
|
}
|
|
}
|
|
|
|
/*
|
|
pathExists : Check if path (file excluded) exists in the structure
|
|
*/
|
|
pathExists(path){
|
|
return(Object.keys(this.path2dir).includes(path))
|
|
}
|
|
|
|
/*
|
|
normalizePath : cleans up and normalizes (executes all /../)
|
|
*/
|
|
normalizePath(path) {
|
|
path = path.replace(/\/+/g, '/')
|
|
if (path.startsWith("/")) path = path.substring(1)
|
|
if (path.endsWith("/")) path = path.slice(0, -1)
|
|
let segments = path.split("/")
|
|
let normalizedPath = "/"
|
|
for(let segment of segments) {
|
|
if (segment === "." || segment === "") continue
|
|
if (segment === "..") {
|
|
normalizedPath = normalizedPath.substring(0, normalizedPath.lastIndexOf("/") )
|
|
continue
|
|
}
|
|
if (!normalizedPath.endsWith("/")) normalizedPath = normalizedPath + "/"
|
|
normalizedPath = normalizedPath + segment
|
|
}
|
|
return(normalizedPath)
|
|
}
|
|
|
|
}
|
|
app.registerClass('FakeFileSystem', FakeFileSystem)
|