fast-glob file discovery with picomatch filters: working versions (tested 2026-10-15)
Find files with fast-glob using ignore lists, dotfile and depth options, and filter paths with compiled picomatch matchers, all against a temp directory fixture.
passed4 passed · 0 failed2026-10-15 17:10 UTC- Status
- passed
- Last passed
- 2026-10-15 17:10 UTC
- Tests
- 4 / 4
- Language
- TypeScript
- Runtime
- node v22.23.3
pinned versions5
fast-glob@3.3.3picomatch@4.0.7@types/node@26.6.5tsx@4.23.15@types/picomatch@4.0.3
run it
npm install --no-audit --no-fund --ignore-scripts=false npm test
test environment
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38775053802
The code
Exactly the files that passed. Your agent can pull them with get_recipe("fast-glob-picomatch-files") (install), or see them on GitHub.
package.json
{
"name": "fast-glob-picomatch-files",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {
"fast-glob": "3.3.3",
"picomatch": "4.0.7"
},
"devDependencies": {
"@types/node": "26.6.5",
"tsx": "4.23.15",
"@types/picomatch": "4.0.3"
}
}
src/files.ts
import fg from "fast-glob";
import picomatch from "picomatch";
export type FindOptions = { cwd: string; ignore?: string[]; dot?: boolean; deep?: number };
export async function findSources({ cwd, ignore = [], dot = false, deep }: FindOptions): Promise<string[]> {
const files = await fg(["**/*.{ts,tsx,js}"], {
cwd,
dot,
deep,
onlyFiles: true,
ignore: ["**/node_modules/**", "**/dist/**", ...ignore],
});
return files.sort();
}
export async function findWithStats(cwd: string, pattern: string) {
const entries = await fg(pattern, { cwd, stats: true, onlyFiles: true });
return entries
.map((e) => ({ path: e.path, size: e.stats!.size }))
.sort((a, b) => a.path.localeCompare(b.path));
}
/** Split paths into test files and others with a compiled matcher (fast for large lists). */
export function partitionTests(paths: string[], patterns = ["**/*.test.*", "**/__tests__/**"]) {
const isTest = picomatch(patterns);
const tests: string[] = [];
const rest: string[] = [];
for (const p of paths) (isTest(p) ? tests : rest).push(p);
return { tests, rest };
}
export function escapeForGlob(name: string): string {
return fg.escapePath(name);
}
test/files.test.ts
import { test, before, after } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { findSources, findWithStats, partitionTests, escapeForGlob } from "../src/files.ts";
let dir = "";
const tree: Record<string, string> = {
"src/index.ts": "export {}",
"src/util/math.ts": "export const add = 1",
"src/util/math.test.ts": "test",
"src/__tests__/e2e.ts": "test",
"src/view.tsx": "<div/>",
"src/readme.md": "# hi",
".config/setup.js": "x",
"dist/index.js": "built",
"node_modules/pkg/index.js": "dep",
"weird [1]/file.ts": "x",
};
before(() => {
dir = fs.mkdtempSync(path.join(os.tmpdir(), "fg-"));
for (const [rel, body] of Object.entries(tree)) {
fs.mkdirSync(path.dirname(path.join(dir, rel)), { recursive: true });
fs.writeFileSync(path.join(dir, rel), body);
}
});
after(() => fs.rmSync(dir, { recursive: true, force: true }));
test("finds sources and skips node_modules, dist and dotfiles", async () => {
assert.deepEqual(await findSources({ cwd: dir }), [
"src/__tests__/e2e.ts", "src/index.ts", "src/util/math.test.ts", "src/util/math.ts", "src/view.tsx", "weird [1]/file.ts",
]);
});
test("dot and deep options", async () => {
const withDot = await findSources({ cwd: dir, dot: true });
assert.ok(withDot.includes(".config/setup.js"));
const shallow = await findSources({ cwd: dir, deep: 2 });
assert.equal(shallow.includes("src/util/math.ts"), false);
assert.ok(shallow.includes("src/index.ts"));
});
test("stats and escaped special characters", async () => {
const stats = await findWithStats(dir, `${escapeForGlob("weird [1]")}/*.ts`);
assert.deepEqual(stats, [{ path: "weird [1]/file.ts", size: 1 }]);
});
test("picomatch partitions test files", async () => {
const { tests, rest } = partitionTests(await findSources({ cwd: dir }));
assert.deepEqual(tests, ["src/__tests__/e2e.ts", "src/util/math.test.ts"]);
assert.equal(rest.length, 4);
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
~/.cursor/mcp.json
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }.vscode/mcp.json
{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }MCP settings
{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.