file-system-access
file-system-access copied to clipboard
Deep file read
My first test of this api, I hit wanting to get deep files immediately. Wanting to do something as simple as
/*
I've removed await/.then() for simplicity sake
[
"./possibly/deep/directory/of/unknown/depth.json",
"./possibly/deep/directory/of/unknown/depth/even/deeper.json",
"./some/other/folder/somewhere.json"
]
*/
const filesToProcess = JSON.parse( folderHandler.getFileHandler("processMe.json").getFile().text() );
for ( const filePath of filesToProcess ) {
// "./possibly/deep/directory/of/unknown/depth.json"
const fileContent = JSON.parse( folderHandler.getFileHandler(filePath).getFile().text() );
doSomethingWith(fileContent);
}
But I ended up having to use the code below,
This is with some caching map, because I didn't want to have to build up the promises of each of the ./possibly/deep/directory/of/unknown/ folder each and every time.
const cache: Map<string, FileSystemDirectoryHandle>= new Map();
const filesToProcess = JSON.parse( folderHandler.getFileHandler("processMe.json").getFile().text() );
for ( const filePath of filesToProcess ) {
// "./possibly/deep/directory/of/unknown/depth.json"
const fileContent = await readFile(files, rootFolderHandler, cache);
doSomethingWith(fileContent);
}
async function readFile(
path: string, // "./possibly/deep/directory/of/unknown/depth.json"
rootFolderHandler: FileSystemDirectoryHandle,
cache: Map<string, FileSystemDirectoryHandle>,
): Promise<any> {
const { folderParts, filename } = getPathParts(path);
const folder = await getFolder(rootFolderHandler, folderParts, cache);
return loadJson(folder.getFileHandle(filename));
}
function getPathParts(path: string): PathParts {
const folderParts = path.split(/\/|\\/g).filter((p) => p !== '.');
const filename = folderParts.pop()!; // assuming the file name is the last part.
return {
folderParts,
filename,
};
}
async function getFolder(
rootFolder: FileSystemDirectoryHandle,
parts: string[],
cache: Map<string, FileSystemDirectoryHandle>,
): Promise<FileSystemDirectoryHandle> {
let currentFolder = rootFolder;
for (let i = 0; i < parts.length; i++) {
const folderName = parts[i];
const path = parts.slice(0, i + 1).join('/');
let pathFolder = cache.get(path);
if (!pathFolder) {
pathFolder = await currentFolder.getDirectoryHandle(folderName); // this is the part that builds up over and over
cache.set(path, pathFolder); // cache so we don't have to do the await over and over again for same folders.
}
currentFolder = pathFolder;
}
return currentFolder;
}
function loadJson(file: Promise<FileSystemFileHandle>): Promise<any> {
return file
.then((fh) => fh.getFile())
.then((f) => f.text())
.then(JSON.parse);
}
This type of stuff would be great if it was just internal. I am 100% confident javascript engine devs could do this stuff 1000% better than my late night botching attempt and I am sure I will not be the only person that would want to do this, especially if the first ever thing I wanted to do, needed it.
Just noticed this was a tiny bullet point on #22 but was buried at the end of the list of other things.