brace-expansion
Bash-style brace expansion for JavaScript, turning patterns like {a,b,c} and {1..5} into arrays of strings.
Repository Health
Technical Analysis
brace-expansion is a small, focused JavaScript implementation of the brace expansion behavior found in sh/bash. Given a pattern such as file-{a,b,c}.jpg or file{0..2}.jpg, it returns the full array of expanded strings, matching Bash’s own expansion rules for comma-separated option lists and numeric or alphabetic ranges (including padding, negative numbers, and reverse iteration).
It underpins some of the most widely used tooling in the JavaScript ecosystem: minimatch and glob both depend on it to support brace patterns in glob expressions, which makes it a transitive dependency of the vast majority of Node.js projects via build tools, linters, and test runners. Recent versions add explicit max and maxLength options to cap the number and total size of expansions, closing a denial-of-service class of vulnerability (CVE-2026-14257) where deeply chained or repeated brace groups could exhaust memory or overflow the call stack.
The library has no runtime dependencies beyond balanced-match, ships as dual ESM/CommonJS output via tshy, and is fully typed in TypeScript.
What You Get
- A single
expand(str, options)function that mirrors Bash’s brace expansion semantics exactly, verified against a large corpus of real Bash output in the test suite - Support for comma-separated option lists (
{a,b,c}), including nested braces ({a,{b,c},d}) - Support for numeric and alphabetic sequences with optional increments and zero-padding (
{1..10..2},{a..e}) - Configurable
maxandmaxLengthoptions to bound the number of expansions and total character output, protecting against DoS from adversarial input - Dual ESM/CommonJS builds with full TypeScript type definitions out of the box
Common Use Cases
- Powering brace-pattern support inside glob-matching libraries like
minimatchandglob - Expanding file name patterns in build tools and CLI utilities that accept shell-style globs
- Generating batches of test fixtures or file names from a single compact pattern
- Safely expanding user-supplied brace patterns in a web service or CLI where input size must be bounded
Under The Hood
Architecture
The library is a single-module implementation in src/index.ts. expand() first escapes literal backslash-escaped braces/commas/periods so they survive parsing, then hands off to an iterative expand_() loop that walks the string’s top-level brace groups left to right using balanced-match to find each matching {/} pair, threading a running array of combined prefixes (acc) through combine() at each step rather than recursing once per top-level group — a deliberate choice (called out in code comments referencing CVE-2026-14257) that keeps native call-stack depth constant regardless of how many brace groups are chained in a single input. Nested groups ({a,{b,c}}) still recurse via parseCommaParts/expand_, but only per nesting level, not per sibling group. combine() is the sole point where output actually grows, and it enforces both the max result-count cap and the maxLength character-count cap inline, so memory stays bounded throughout rather than being checked only after a large intermediate array is built.
Tech Stack
Pure TypeScript with a single runtime dependency, balanced-match, used to locate matching brace pairs. The package is built with tshy, producing dual ESM (dist/esm) and CommonJS (dist/commonjs) outputs with generated .d.ts files for both, so consumers get native ESM or CJS imports plus full type information without a separate typings package. prettier handles formatting and typedoc generates API docs from the TSDoc comments in src/index.ts. No web framework, database, or build bundler beyond tshy itself is involved — this is a leaf utility package.
Code Quality
Tests run under tap and are data-driven: test/bash-results.txt contains real Bash brace-expansion output for a large set of patterns (generated by test/generate.sh, which presumably shells out to actual Bash), and the suite asserts the JS implementation’s output matches Bash exactly for every case, plus targeted unit tests for edge cases like ${ sequences and empty options. Functions are small, named descriptively (parseCommaParts, expandSequence, combine), and comments explicitly document the reasoning behind non-obvious choices, including the CVE fix and Bash quirks being intentionally replicated. CI (.github/workflows/ci.yml) runs a formatting check plus a build/test matrix across Node 20/22/24/25 on Ubuntu, macOS, and Windows (both bash and PowerShell shells), giving strong confidence in cross-platform correctness for a package this foundational.
API Design
The public surface is intentionally minimal: one exported function, expand(str, options), with an optional { max, maxLength } options object and two exported constants (EXPANSION_MAX, EXPANSION_MAX_LENGTH) documenting the defaults. There is no configuration object to construct, no class to instantiate, and no boilerplate beyond a single import — consumers can be productive from the README’s first code example. The tradeoff for this simplicity is that safety limits are opt-in tuning knobs rather than the primary interface; the defaults are sensible but a caller processing untrusted input still needs to know the options exist.