@stll/text-search
Multi-engine text search orchestrator for
Node.js and Bun. Routes patterns to the optimal
engine automatically: Aho-Corasick for literals,
RegexSet for regex, FuzzySearch for approximate
matching, with auto-optimization for large
alternations.
Part of the
@stll text search ecosystem:
@stll/regex-set,
@stll/aho-corasick,
@stll/fuzzy-search.
Install
npm install @stll/text-search
bun add @stll/text-search
Requires @stll/regex-set, @stll/aho-corasick,
and @stll/fuzzy-search as peer dependencies
(installed automatically).
Usage
import { TextSearch } from "@stll/text-search";
const ts = new TextSearch([
/\b\d{2}\.\d{2}\.\d{4}\b/,
/\b[\w.+-]+@[\w-]+\.[\w]+\b/,
"Confidential",
"Attorney-Client Privilege",
{ pattern: "Novák", distance: 1, name: "person" },
`(?:${titles.join("|")})\\s+[A-Z][a-z]+`,
{ pattern: /\+?\d{9,12}/, name: "phone" },
]);
ts.findIter("Ing. Jan Novak, born 15.03.1990");
Engine routing
Patterns are classified and routed to the optimal
engine at construction time:
| Aho-Corasick | Pure literal strings | SIMD-accelerated |
| RegexSet (shared) | Normal regex patterns | Single-pass DFA |
| RegexSet (isolated) | >50 alternation branches | Prevents DFA explosion |
| FuzzySearch | distance field present | Levenshtein/Damerau |
Large alternation patterns (e.g., 80+ title
prefixes) are automatically isolated into their
own RegexSet instance, preventing DFA state
explosion when combined with other patterns.
new RegexSet([hugePattern, simplePattern]);
new TextSearch([hugePattern, simplePattern]);
Options
new TextSearch(patterns, {
unicodeBoundaries: true,
wholeWords: false,
maxAlternations: 50,
fuzzyMetric: "levenshtein",
normalizeDiacritics: false,
caseInsensitive: false,
});
API
findIter(text) | Match[] | All non-overlapping matches |
isMatch(text) | boolean | Any pattern matches? |
whichMatch(text) | number[] | Which pattern indices matched |
replaceAll(text, replacements) | string | Replace matches |
length | number | Number of patterns |
Pattern entry types
"foo"
/\btest\b/i
{ pattern: "\\d+", name: "number" }
{ pattern: "Novák", distance: 1 }
{ pattern: "Smith", distance: "auto", name: "person" }
Match type
type Match = {
pattern: number;
start: number;
end: number;
text: string;
name?: string;
};
Same Match shape as @stll/regex-set,
@stll/aho-corasick, and @stll/fuzzy-search.
How it works
- Classify: detect literals, count alternation
branches, identify fuzzy patterns
- Route: literals → AC, fuzzy → FuzzySearch,
large alternations → isolated RegexSet,
normal regex → shared RegexSet
- Search: each engine scans the text
- Merge: combine results, sort by position,
select non-overlapping (longest match at ties)
Development
bun install
bun test
bun run lint
bun run format
bun run build
Built on
License
MIT