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

@ferrow/glob-path-matcher

v1.0.0

Published

Zero-dependency glob path matching: *, **, ?, [abc]/[a-z] classes, {a,b} braces, negation, dotfile policy, case sensitivity, a compile() reusable matcher, and matchList() with .gitignore-style negation-order semantics.

Readme

glob-path-matcher

CI

Zero-dependency glob path matching for TypeScript/JavaScript: *, **, ?, [abc]/[a-z]/[!abc] character classes, {a,b} brace alternation, ! negation, a configurable dotfile policy, case sensitivity, and a matchList() with .gitignore-style negation-order semantics.

Why

Agents constantly need to test paths against include/exclude patterns — tool allow-lists, file-scoping rules, .gitignore-style filters — without pulling in minimatch/micromatch. This package implements the common glob subset with zero runtime dependencies and safe pattern-to-regex conversion (every literal character is escaped; nothing from the input pattern is ever interpreted as raw regex).

Install

npm install glob-path-matcher

Quickstart

import { compile, match, matchList } from "glob-path-matcher";

match("src/**/*.{js,ts}", "src/deep/nested/file.js"); // true

const matcher = compile("*.log", { caseSensitive: false });
matcher.test("DEBUG.LOG"); // true

matchList(["*.log", "!important.log"], ["debug.log", "important.log", "notes.txt"]);
// ["debug.log"] — matched by *.log, not re-excluded; important.log matched then un-matched by !important.log

API

compile(pattern: string, options?: GlobOptions): CompiledMatcher

Compiles a pattern once for reuse. CompiledMatcher = { pattern: string; negated: boolean; test(path: string): boolean }. A leading ! sets .negated but does not affect .test() itself — negation is a list-level concept, handled by matchList.

match(pattern: string, path: string, options?: GlobOptions): boolean

One-shot convenience: compile(pattern, options).test(path).

matchList(patterns: string[], paths: string[], options?: GlobOptions): string[]

Applies patterns to paths in order, .gitignore-style: a path is included in the result if the last pattern that matches it is not negated. A later !pattern can un-match an earlier hit, and a later positive pattern can re-match again after that. Paths matched by no pattern are excluded.

expandBraces(pattern: string): string[]

The brace-expansion step used internally, exported standalone — e.g. expandBraces("*.{js,ts}") -> ["*.js", "*.ts"].

interface GlobOptions {
  caseSensitive?: boolean; // default true
  dot?: boolean;           // default false — see Dotfile policy below
}

Glob syntax supported

| Token | Meaning | |---|---| | * | any run of characters within one path segment (no /), including empty | | ** | any number of whole path segments (including zero) | | ? | exactly one character within a segment | | [abc], [a-z], [!abc]/[^abc] | character class / negated class | | {a,b,c} | brace alternation (expanded before matching; not nested) | | !pattern (as the whole pattern) | negation marker, used by matchList |

Dotfile policy

By default (dot: false), *, **, and ? never match a path segment starting with . — matching shell-glob/.gitignore convention — unless the corresponding pattern segment itself literally starts with . (e.g. .env* matches .env.local even with dot: false, but *.js does not match .hidden.js unless dot: true).

Limits

  • Patterns are relative, /-separated segment lists — no leading-/ absolute-path semantics, no Windows \ separators (normalize first).
  • {a,b} brace groups are not nested ({a,{b,c}} expands its literal text rather than recursing) — flat/multiple groups in one pattern work fine.
  • Character classes don't support escaped ] inside the class or POSIX classes like [[:alpha:]].
  • ** only has its "span zero-or-more segments" meaning as a whole path segment; a**b is treated as two ordinary * wildcards, not a ** span.

Part of the ferrow-toolkit collection · Sponsored by Ferrow