fast-glob icon indicating copy to clipboard operation
fast-glob copied to clipboard

[Feature Request] Option to ignore file existence of static (non-glob) patterns

Open swebra opened this issue 1 year ago • 0 comments

Currently fast-glob silently omits any input files which do not exist from its output; this makes sense given that glob patterns need to be dropped in favor of the corresponding found files. However, in the context of a CLI tool for example, one might want to warn a user if a static pattern was not found given that a static path may be more intentional. As far as I can tell, because of the omission behavior, there isn't a super elegant way to achieve this.

If you pass a file list through fast-glob and intend to throw warnings when you read said files, any non-existing files will already be omitted by fast-glob:

import { sync } from "fast-glob";
import { readFileSync } from "fs";

let inputPaths = ["path/does/not.exist", "/some/*/glob/**"];
inputPaths = sync(inputPaths, { unique: true }); // expand globs

inputPaths.forEach((filePath) => {
  try {
    const contents = readFileSync(filePath, "utf-8");
    // Do something with contents
  } catch (err) {
    console.warn(`Could not open ${filePath}`);
  }
});

// will never warn about path/does/not.exist because `sync` call (line 5) strips it away

You can instead use isDynamicPattern to only pass dynamic patterns to sync...

import { isDynamicPattern, sync } from "fast-glob";
import { readFileSync } from "fs";

function expandInputPaths(paths: string[]): string[] {
  const splitPaths = paths.reduce(
    (acc, path) => {
      acc[isDynamicPattern(path) ? "glob" : "globless"].push(path);
      return acc;
    },
    { glob: [], globless: [] } as { glob: string[]; globless: string[] }
  );

  const recombinedPaths = sync(splitPaths["glob"]).concat(splitPaths["globless"]);
  return [...new Set(recombinedPaths)]; // remove duplicates
}

let inputPaths = ["path/does/not.exist", "/some/*/glob/**"];
inputPaths = expandInputPaths(inputPaths); // expand globs

inputPaths.forEach((filePath) => {
  try {
    const contents = readFileSync(filePath, "utf-8");
    // Do something with contents
  } catch (err) {
    console.warn(`Could not open ${filePath}`);
  }
});

... but a) this has to repeat the iteration and checks that sync is already doing, and b) this doesn't allow you to use the nice fast-glob options like unique (because you aren't passing all the files to fast-glob)

I'm thinking if fast-glob had a way to keep the static patterns which don't exist, the first example would work. I'm welcome to suggestions of other ways to approach this as well.

swebra avatar Feb 02 '23 00:02 swebra