@squawk
    Preparing search index...

    Module @squawk/search

    Domain-agnostic fuzzy string matching and ranked search scoring.

    Two entry points: fuzzyScore scores a query against a single candidate string (returning a normalised [0, 1] score plus matched character ranges), and fuzzySearch ranks a list of items across one or more searchable fields. The package holds no domain knowledge; callers supply the fields to search and any filtering predicate.

    import { fuzzyScore, fuzzySearch } from '@squawk/search';

    fuzzyScore('jfk', 'JFK'); // { score: 1, ranges: [{ start: 0, end: 3 }] }

    const matches = fuzzySearch(airports, 'kennedy', {
    keys: (a) => [
    { name: 'faaId', text: a.faaId },
    { name: 'name', text: a.name },
    ],
    limit: 10,
    });

    squawk logo  @squawk/search

    MIT License npm TypeScript

    Domain-agnostic fuzzy string matching and ranked search scoring. A small, dependency-free engine that scores how well a query matches a candidate string (exact, prefix, substring, subsequence, and bounded typo tiers), returns a normalised [0, 1] score plus the matched character ranges for UI highlighting, and ranks a list of items across one or more searchable fields.

    Documentation

    Part of the @squawk aviation library suite. See all packages on npm.

    This package holds no aviation domain knowledge. It is the shared scoring substrate used by the @squawk/* resolvers (airports, navaids, fixes, airways, airspace) to power their search() methods, and can be used standalone for any fuzzy-matching need.

    npm install @squawk/search
    

    fuzzyScore compares a query against one candidate string and returns a normalised score in [0, 1] (1 = exact, 0 = no match) along with the matched character ranges:

    import { fuzzyScore } from '@squawk/search';

    fuzzyScore('jfk', 'JFK'); // { score: 1, ranges: [{ start: 0, end: 3 }] }
    fuzzyScore('ken', 'Kennedy'); // strong prefix match, ranges cover "Ken"
    fuzzyScore('kndy', 'Kennedy'); // subsequence match, lower score
    fuzzyScore('jfx', 'JFK'); // bounded typo match, lower score still
    fuzzyScore('xyz', 'JFK'); // { score: 0, ranges: [] }

    fuzzySearch ranks a list of arbitrary items against a query. You describe how to extract the searchable fields from each item; the engine scores every field, keeps the best per item, filters, sorts by descending score, and slices to limit:

    import { fuzzySearch } from '@squawk/search';

    interface Station {
    id: string;
    name: string;
    }

    const stations: Station[] = [
    { id: 'JFK', name: 'John F Kennedy Intl' },
    { id: 'EWR', name: 'Newark Liberty Intl' },
    { id: 'LGA', name: 'LaGuardia' },
    ];

    const matches = fuzzySearch(stations, 'kennedy', {
    keys: (s) => [
    { name: 'id', text: s.id },
    { name: 'name', text: s.name },
    ],
    limit: 10,
    });

    // matches[0] => { item: { id: 'JFK', ... }, score, field: 'name', ranges: [...] }
    • Tiered scoring: Exact, prefix, word-boundary prefix, substring, subsequence, and bounded Damerau-Levenshtein typo tiers, collapsed into a single normalised [0, 1] score so results are comparable across fields and data sets.
    • Match ranges: Every score carries the matched character ranges, ready for highlight rendering in a UI.
    • Multi-field ranking: Score an item across several fields and keep the best-matching one, with the matched field name reported on each result.
    • Caller-supplied filtering: Pass a predicate to exclude items before scoring (e.g. respecting visibility or type filters) without the engine knowing anything about the domain.
    • Zero dependencies: Pure string logic with no runtime dependencies.

    Interfaces

    FuzzyMatch
    FuzzyScore
    FuzzySearchOptions
    MatchRange
    SearchField

    Functions

    fuzzyScore
    fuzzySearch