Graphmatch
Graphmatch is a low-level utility designed for matching a string against a directed acyclic graph (DAG) composed of regular expressions. It provides flexible matching capabilities, supporting both full and partial string matches against these complex regex structures. Developers can exercise fine-grained control over partial matching behavior at the individual node level within the graph. A key feature is the ability to compile the entire graph into a single JavaScript RegExp object, which significantly optimizes performance for scenarios requiring multiple matches against the same graph. The package is currently at version 1.1.1 and appears to be actively maintained, though no specific release cadence is outlined in the documentation. Its core differentiation lies in offering a programmatic, graph-based approach to regex matching, which is more powerful and manageable than composing single, overly complex regular expressions or chaining multiple simple ones, particularly useful for structured pattern recognition like advanced globbing.
Common errors
-
TypeError: (0 , graphmatch_1.default) is not a function
cause Incorrect CommonJS `require` usage for a package that primarily offers an ESM default export, or attempting to use a default import in a CommonJS context without proper transpilation.fixFor native ESM, use `import graphmatch from 'graphmatch';`. If in a CommonJS environment, you might need to use `const graphmatch = require('graphmatch').default;` or ensure your build setup correctly transpiles ESM imports. -
TypeError: Cannot read properties of undefined (reading 'compile')
cause Attempting to access `compile` on an undefined `graphmatch` object, often due to an incorrect import where the default export was not successfully captured, or treating `compile` as a named export.fixVerify that `import graphmatch from 'graphmatch';` is correctly acquiring the default export. The `compile` method is a property of the default `graphmatch` function, not a separate named export. -
TypeError: Invalid regular expression: /.../: Flags can't be modified (or similar error related to RegExp flags)
cause Using regular expressions within the graph that have inconsistent flags (e.g., one with 'i' and another without), which `graphmatch` does not support across a single graph structure.fixReview all `regex` properties in your graph definition and ensure that they all use the exact same set of RegExp flags, or no flags at all. For example, `regex: /pattern/i` should be consistent for all regexes if `i` is desired.
Warnings
- gotcha All regular expressions within a single graph must use the same RegExp flags (e.g., 'i', 'g', 'm'). Mixing flags across different nodes in the same graph is not supported and will lead to unexpected behavior or errors.
- gotcha The graph matching process always begins from the very start of the input string. It does not support arbitrary starting positions within the string.
- gotcha As a 'low-level utility', `graphmatch` expects a well-formed graph of regexes. Malformed graph structures (e.g., cycles in a DAG, invalid `regex` properties, or incorrect `children` arrays) are not explicitly validated beyond basic runtime checks and can lead to unexpected behavior or crashes.
- gotcha For repeated matching against the same graph, directly calling the `graphmatch` function multiple times can be less performant than pre-compiling the graph. The internal compilation step has an overhead.
Install
-
npm install graphmatch -
yarn add graphmatch -
pnpm add graphmatch
Imports
- graphmatch
const graphmatch = require('graphmatch');import graphmatch from 'graphmatch';
- graphmatch.compile
import { compile } from 'graphmatch'; // This is incorrect, compile is a property of the default exportimport graphmatch from 'graphmatch'; const compiledRegex = graphmatch.compile(GRAPH_DEFINITION);
- GraphNode
type GraphNode = { regex: RegExp; children?: GraphNode[]; partial?: boolean; };
Quickstart
import graphmatch from 'graphmatch';
const GRAPH = {
regex: /foo/,
children: [
{
regex: /\//,
children: [
{
regex: /bar/,
children: [
{
regex: /\//,
children: [
{
regex: /qux/
}
]
}
]
},
{
regex: /baz/,
children: [
{
regex: /\//,
children: [
{
regex: /qux/
}
]
}
]
}
]
}
]
};
// Match against the graph fully
console.log('Full match `foo/bar/qux`:', graphmatch(GRAPH, 'foo/bar/qux')); // => true
console.log('Full match `foo/baz`:', graphmatch(GRAPH, 'foo/baz')); // => false
// Match against the graph partially
console.log('Partial match `foo/bar/`:', graphmatch(GRAPH, 'foo/bar/', { partial: true })); // => true
console.log('Partial match `bar`:', graphmatch(GRAPH, 'bar', { partial: true })); // => false
// Compile the graph to a single regex for repeated, efficient matching
const fullCompiledRe = graphmatch.compile(GRAPH);
console.log('Compiled regex test `foo/bar/qux`:', fullCompiledRe.test('foo/bar/qux')); // => true
console.log('Compiled regex test `foo/bar`:', fullCompiledRe.test('foo/bar')); // => false
const partialCompiledRe = graphmatch.compile(GRAPH, { partial: true });
console.log('Compiled partial regex test `foo/bar`:', partialCompiledRe.test('foo/bar')); // => true