From cf350d6b346d867e5bd297d4ea6d3b7b1ac608fd Mon Sep 17 00:00:00 2001 From: Kaylee <65376239+KayleeWilliams@users.noreply.github.com> Date: Mon, 11 May 2026 11:26:55 -0700 Subject: [PATCH 1/2] Replace fast-glob with tinyglobby MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop-in swap of the globbing dep. Cuts 13 transitive packages and ~80% of installed bytes (1.2 MB → 240 KB) for the same call sites in lint, convert, generate, and the evals tool harness. All existing glob options (absolute, onlyFiles, ignore, dot, followSymbolicLinks, cwd) carry over with identical results across the repo's call sites. --- .changeset/replace-fast-glob-with-tinyglobby.md | 5 +++++ bun.lock | 6 +++--- evals/lib/tools.ts | 2 +- evals/package.json | 2 +- packages/leadtype/package.json | 2 +- packages/leadtype/src/cli.test.ts | 2 +- packages/leadtype/src/cli/generate.ts | 2 +- packages/leadtype/src/convert/convert.ts | 2 +- packages/leadtype/src/lint/runner.ts | 2 +- 9 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 .changeset/replace-fast-glob-with-tinyglobby.md diff --git a/.changeset/replace-fast-glob-with-tinyglobby.md b/.changeset/replace-fast-glob-with-tinyglobby.md new file mode 100644 index 0000000..9783b07 --- /dev/null +++ b/.changeset/replace-fast-glob-with-tinyglobby.md @@ -0,0 +1,5 @@ +--- +"leadtype": patch +--- + +Replace `fast-glob` with `tinyglobby` to shrink the dependency tree (16 transitive deps → 3) and reduce install footprint (~1.2 MB → ~240 KB). Globbing behavior and call-site options are unchanged. diff --git a/bun.lock b/bun.lock index ef633ae..7a03cd5 100644 --- a/bun.lock +++ b/bun.lock @@ -73,19 +73,18 @@ "version": "0.0.0", "devDependencies": { "ai": "^6.0.168", - "fast-glob": "3.3.3", + "tinyglobby": "0.2.16", "vitest": "^2.1.8", "zod": "^3.23.8", }, }, "packages/leadtype": { "name": "leadtype", - "version": "0.0.0", + "version": "0.1.0", "bin": "./dist/cli.js", "dependencies": { "@types/mdast": "4.0.4", "decode-named-character-reference": "1.3.0", - "fast-glob": "3.3.3", "gray-matter": "4.0.3", "jiti": "^2.7.0", "json5": "2.2.3", @@ -95,6 +94,7 @@ "remark": "15.0.1", "remark-gfm": "4.0.1", "remark-mdx": "3.1.1", + "tinyglobby": "0.2.16", "unified": "11.0.5", "unist-builder": "4.0.0", "unist-util-is": "6.0.1", diff --git a/evals/lib/tools.ts b/evals/lib/tools.ts index 5f1917c..67593df 100644 --- a/evals/lib/tools.ts +++ b/evals/lib/tools.ts @@ -2,7 +2,7 @@ import { spawn } from "node:child_process"; import { mkdir, readdir, readFile, writeFile } from "node:fs/promises"; import path from "node:path"; import { tool } from "ai"; -import fg from "fast-glob"; +import { glob as fg } from "tinyglobby"; import { z } from "zod"; import type { ToolCall } from "./transcript"; diff --git a/evals/package.json b/evals/package.json index 2b10dcd..e7413a4 100644 --- a/evals/package.json +++ b/evals/package.json @@ -12,7 +12,7 @@ }, "devDependencies": { "ai": "^6.0.168", - "fast-glob": "3.3.3", + "tinyglobby": "0.2.16", "vitest": "^2.1.8", "zod": "^3.23.8" } diff --git a/packages/leadtype/package.json b/packages/leadtype/package.json index 55a53cf..9351256 100644 --- a/packages/leadtype/package.json +++ b/packages/leadtype/package.json @@ -92,7 +92,6 @@ "dependencies": { "@types/mdast": "4.0.4", "decode-named-character-reference": "1.3.0", - "fast-glob": "3.3.3", "gray-matter": "4.0.3", "jiti": "^2.7.0", "json5": "2.2.3", @@ -102,6 +101,7 @@ "remark": "15.0.1", "remark-gfm": "4.0.1", "remark-mdx": "3.1.1", + "tinyglobby": "0.2.16", "unified": "11.0.5", "unist-builder": "4.0.0", "unist-util-is": "6.0.1", diff --git a/packages/leadtype/src/cli.test.ts b/packages/leadtype/src/cli.test.ts index da6b774..368d1c7 100644 --- a/packages/leadtype/src/cli.test.ts +++ b/packages/leadtype/src/cli.test.ts @@ -3,7 +3,7 @@ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import fg from "fast-glob"; +import { glob as fg } from "tinyglobby"; import { afterEach, describe, expect, it } from "vitest"; import { runCli } from "./cli"; diff --git a/packages/leadtype/src/cli/generate.ts b/packages/leadtype/src/cli/generate.ts index f421414..50d72ad 100644 --- a/packages/leadtype/src/cli/generate.ts +++ b/packages/leadtype/src/cli/generate.ts @@ -2,9 +2,9 @@ import { existsSync } from "node:fs"; import { cp, mkdir, mkdtemp, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; -import fg from "fast-glob"; import matter from "gray-matter"; import { createJiti } from "jiti"; +import { glob as fg } from "tinyglobby"; import { convertAllMdx } from "../convert"; import { logger, diff --git a/packages/leadtype/src/convert/convert.ts b/packages/leadtype/src/convert/convert.ts index 5767013..9d5e28d 100644 --- a/packages/leadtype/src/convert/convert.ts +++ b/packages/leadtype/src/convert/convert.ts @@ -4,11 +4,11 @@ import { mkdir, readFile, writeFile } from "node:fs/promises"; import { cpus } from "node:os"; import { basename, dirname, join, relative, resolve, sep } from "node:path"; import { promisify } from "node:util"; -import fg from "fast-glob"; import matter from "gray-matter"; import { remark } from "remark"; import remarkGfm from "remark-gfm"; import remarkMdx from "remark-mdx"; +import { glob as fg } from "tinyglobby"; import type { Pluggable, PluggableList } from "unified"; import { deriveDocContext, diff --git a/packages/leadtype/src/lint/runner.ts b/packages/leadtype/src/lint/runner.ts index 8b14f17..8466a5b 100644 --- a/packages/leadtype/src/lint/runner.ts +++ b/packages/leadtype/src/lint/runner.ts @@ -1,10 +1,10 @@ import { existsSync } from "node:fs"; import { readFile } from "node:fs/promises"; import { relative, resolve, sep } from "node:path"; -import fg from "fast-glob"; import matter from "gray-matter"; import { remark } from "remark"; import remarkGfm from "remark-gfm"; +import { glob as fg } from "tinyglobby"; import { visit } from "unist-util-visit"; import * as v from "valibot"; import { convertMdxToMarkdown } from "../convert"; From 70603c7b1a9ff254570fd1e6ff8cdcb6ef85237d Mon Sep 17 00:00:00 2001 From: Kaylee <65376239+KayleeWilliams@users.noreply.github.com> Date: Mon, 11 May 2026 11:34:17 -0700 Subject: [PATCH 2/2] Pin expandDirectories: false at user-pattern call sites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tinyglobby expands bare directory names (`build` → `build/**`) by default; fast-glob did not. Without this option, `leadtype generate --include build` silently slurped every MDX file under `docs/build/` instead of reporting "No MDX files matched" the way fast-glob did with `onlyFiles: true`. Disable expandDirectories at the three call sites that take user-/agent-supplied patterns: - packages/leadtype/src/cli/generate.ts (CLI --include/--exclude) - packages/leadtype/src/lint/runner.ts (LintOptions ignore) - evals/lib/tools.ts (agent-facing glob tool) Hardcoded patterns elsewhere (**/*.mdx, **/*, leadtype-generate-*) can't trigger directory expansion, so they're left alone. Regression test covers the exact `--include ` path. --- evals/lib/tools.ts | 3 +++ packages/leadtype/src/cli.test.ts | 32 +++++++++++++++++++++++++++ packages/leadtype/src/cli/generate.ts | 5 +++++ packages/leadtype/src/lint/runner.ts | 3 +++ 4 files changed, 43 insertions(+) diff --git a/evals/lib/tools.ts b/evals/lib/tools.ts index 67593df..445107d 100644 --- a/evals/lib/tools.ts +++ b/evals/lib/tools.ts @@ -235,6 +235,9 @@ export function scopedTools(ctx: ToolCtx) { absolute: false, dot: false, followSymbolicLinks: false, + // Agent supplies the pattern; keep fast-glob semantics so a + // bare directory name doesn't silently expand to `dir/**`. + expandDirectories: false, }); return matches.join("\n"); }, diff --git a/packages/leadtype/src/cli.test.ts b/packages/leadtype/src/cli.test.ts index 368d1c7..4774b1a 100644 --- a/packages/leadtype/src/cli.test.ts +++ b/packages/leadtype/src/cli.test.ts @@ -524,6 +524,38 @@ describe("leadtype CLI", () => { expect(error.filters.include).toEqual(["nope/**"]); }); + it("treats a bare directory in --include as matching no MDX files", async () => { + // tinyglobby expands bare directory names to `dir/**` by default; fast-glob + // didn't. With expandDirectories disabled at the call site, `--include build` + // should fail the same way `--include nope` does — not silently include + // every file under `docs/build/`. + const outDir = await createTempDir(); + const capture = createCapture(); + + const code = await runCli( + [ + "generate", + "--src", + repoRoot, + "--out", + outDir, + "--include", + "build", + "--format", + "json", + ], + capture.io + ); + + expect(code).toBe(1); + const error = JSON.parse(capture.stderr) as { + error: string; + filters: { include: string[] }; + }; + expect(error.error).toContain("No MDX files matched"); + expect(error.filters.include).toEqual(["build"]); + }); + it("rejects invalid generate formats as usage errors", async () => { const capture = createCapture(); diff --git a/packages/leadtype/src/cli/generate.ts b/packages/leadtype/src/cli/generate.ts index 50d72ad..16372b2 100644 --- a/packages/leadtype/src/cli/generate.ts +++ b/packages/leadtype/src/cli/generate.ts @@ -436,6 +436,11 @@ async function createSourceMirror( const files = await fg(patterns, { absolute: false, cwd: docsDir, + // tinyglobby expands bare directory names (`build` → `build/**`) by + // default; fast-glob did not. Disable it so `--include build` still + // reports "No MDX files matched" instead of silently slurping everything + // under `build/`. + expandDirectories: false, ignore: filters.exclude, onlyFiles: true, }); diff --git a/packages/leadtype/src/lint/runner.ts b/packages/leadtype/src/lint/runner.ts index 8466a5b..84fc211 100644 --- a/packages/leadtype/src/lint/runner.ts +++ b/packages/leadtype/src/lint/runner.ts @@ -97,6 +97,9 @@ async function glob( onlyFiles: true, ignore, dot: false, + // Preserve fast-glob semantics: callers can pass user-supplied ignores, + // and bare directory entries should not auto-expand to `dir/**`. + expandDirectories: false, }); }