npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@neodx/glob

v1.0.0

Published

Fast glob matching and path walking helpers

Readme

@neodx/glob

Low-level glob matching and path walking helpers — a small, dependency-light toolkit for matching paths against glob patterns, compiling globs to regular expressions, checking ignore rules, and walking a reader-supplied set of paths.

@neodx/glob is a foundation package: it backs the product packages (vfs, svg, …) and is also published for direct use. The surface is small and intended to stay stable. The matching engine is inspired by zeptomatch and built on the grammex grammar framework, which is bundled into the published artifact (no runtime dependency on it).

Visit https://neodx.pages.dev/glob/ for the full guide.

Installation

# yarn
yarn add @neodx/glob
# npm
npm install @neodx/glob
# pnpm
pnpm install @neodx/glob

Getting started

Match a single path, or compile a pattern into a reusable matcher:

import { matchGlob, createGlobMatcher } from '@neodx/glob';

matchGlob('**/*.ts', 'src/index.ts'); // true
matchGlob('**/*.ts', 'src/index.js'); // false

const isSource = createGlobMatcher(['src/**/*.ts', 'src/**/*.tsx']);
isSource('src/app/index.ts'); // true
isSource('dist/index.js'); // false

For collecting results from a real (or virtual) tree, walkGlob extracts the static base paths from the pattern and asks a caller-supplied reader for the entries under each base — see the API overview below.

Benchmark

Benchmarks are powered by Vitest, you can run them with the yarn bench command.

Source code of the benchmark is located in src/__tests__/glob.bench.ts.

Results on my machine:

 ✓ src/__tests__/glob.bench.ts (8) 6415ms
   ✓ match("**/*.ts", "libs/some/path/to/file.ts") (4) 5882ms
     name                          hz     min      max    mean     p75     p99    p995    p999     rme  samples
   · @neodx/glob         1,141,205.65  0.0006   3.5866  0.0009  0.0008  0.0027  0.0034  0.0213  ±2.08%   570603   fastest
   · picomatch             706,530.46  0.0011   3.7150  0.0014  0.0014  0.0029  0.0042  0.0255  ±1.85%   353266
   · zeptomatch            875,495.74  0.0009   5.2446  0.0011  0.0011  0.0020  0.0028  0.0235  ±2.34%   437748
   · micromatch.isMatch    668,186.93  0.0011  12.1941  0.0015  0.0013  0.0039  0.0053  0.0254  ±5.73%   334094   slowest
   ✓ match("base/{a,b}/**/*.{config,test}.[jt]s", "base/a/my-config.js") (4) 6412ms
     name                          hz     min      max    mean     p75     p99    p995    p999      rme  samples
   · @neodx/glob         1,342,514.61  0.0006   1.1806  0.0007  0.0007  0.0015  0.0021  0.0210   ±1.00%   671258   fastest
   · picomatch              77,828.40  0.0054  15.9870  0.0128  0.0095  0.0321  0.0440  0.3226  ±12.88%    38999   slowest
   · zeptomatch            778,006.62  0.0010  15.1421  0.0013  0.0012  0.0022  0.0029  0.0233   ±6.29%   389004
   · micromatch.isMatch     82,422.61  0.0062   9.6787  0.0121  0.0093  0.0326  0.0490  0.3296  ±10.51%    41212


 BENCH  Summary

  @neodx/glob - src/__tests__/glob.bench.ts > match("**/*.ts", "libs/some/path/to/file.ts")
    1.30x faster than zeptomatch
    1.62x faster than picomatch
    1.71x faster than micromatch.isMatch

  @neodx/glob - src/__tests__/glob.bench.ts > match("base/{a,b}/**/*.{config,test}.[jt]s", "base/a/my-config.js")
    1.73x faster than zeptomatch
    16.29x faster than micromatch.isMatch
    17.25x faster than picomatch

Motivation

@neodx/glob was created to provide a simple, fast and highly featured glob matching toolchain for the neodx ecosystem.

Inspiration

This project got inspiration about API design and some features from the following projects:

  • Thanks zeptomatch for grammex and primary implementation reference

API overview

The source under src is the source of truth for the current Public API; everything below is re-exported from the root . entry. Patterns support the usual glob syntax (*, **, ?, character classes [abc] / [a-z], brace expansion {a,b}, brace ranges {1..9} / {a..z}, and negation !). On Windows-style backslash separators paths are normalized to / before matching.

Matching

| Export | Signature | Purpose | | ------------------- | --------------------------------------------------------- | --------------------------------------------------------------------- | | matchGlob | (glob: string \| string[], path: string) => boolean | Match a single path against one or more patterns. | | createGlobMatcher | (glob: string \| string[]) => (path: string) => boolean | Compile patterns once into a reusable matcher (memoized per pattern). | | globToRegExp | (glob: string) => RegExp | Compile a single pattern into an anchored RegExp (^…$, dotall). |

Escaping and static detection

| Export | Signature | Purpose | | -------------- | --------------------------- | -------------------------------------------------------------------------------------------- | | escapeGlob | (glob: string) => string | Escape glob metacharacters so a literal pattern matches itself (e.g. *.js\*\.js). | | unescapeGlob | (glob: string) => string | Reverse escapeGlob: strip \ escapes. | | isStaticGlob | (glob: string) => boolean | true when a pattern contains no unescaped glob metacharacters (matches as a literal path). |

Path extraction and walking

| Export | Signature | Purpose | | --------------------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | parseGlobPaths | (glob: string) => [paths: string[], glob: string] | Split a pattern into its static leading base paths and the remaining dynamic glob. | | extractGlobPaths | (glob: string \| string[]) => [path: string, patterns: string[]][] | Group an array of patterns by shared base path, expanding brace alternatives ({a,b}) into separate bases. Returned to walkGlob. | | createIgnoreChecker | (ignore: WalkIgnoreInput) => WalkPathChecker | Normalize an ignore rule (function, RegExp, pattern, or patterns) into a (path) => boolean checker. | | walkGlob | (glob, WalkGlobParams<Item, Result>) => Promise<Result[]> | Extract base paths, call a caller-supplied reader for each, and collect matched, non-ignored results. Reader-driven (no built-in FS). |

walkGlob does not read the file system itself. For each base path it invokes the supplied reader with a WalkReaderParams (path, match, isMatched, isIgnored, signal), then filters the returned items through match. Use mapPath to read a path off each item and mapResult to shape the output (defaults produce joined relative paths).

Types

| Export | Purpose | | ---------------------- | -------------------------------------------------------------------------------------------- | | WalkGlobParams | Options for walkGlob: reader (required), mapPath, mapResult, plus the common params. | | WalkGlobCommonParams | Shared options usable by higher-level walkers: timeout, ignore, signal, log. | | WalkReaderParams | Context passed to each reader call: path, match, isMatched, isIgnored, signal. | | WalkIgnoreInput | Accepted ignore shape: WalkPathChecker \| RegExp \| string \| string[]. | | WalkPathChecker | (path: string) => boolean. |

License

MIT