file-system-access icon indicating copy to clipboard operation
file-system-access copied to clipboard

Deep file read

Open WORMSS opened this issue 4 years ago • 1 comments

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.

WORMSS avatar Dec 21 '20 09:12 WORMSS

Just noticed this was a tiny bullet point on #22 but was buried at the end of the list of other things.

WORMSS avatar Dec 21 '20 09:12 WORMSS