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

wovvmap-search-core

v1.0.8

Published

A production-ready, cross-platform Smart Search package.

Downloads

1,009

Readme

wovvmap-search-core 🚀

A high-performance, production-ready Smart Search utility for JavaScript and TypeScript apps. It features a robust internal scoring system including exact matches, prefix matches, token-overlap matching, and Enterprise-Grade Smart Fuzzy (typo-tolerant) searching!

Whether you're building a React frontend, a React Native mobile app, or a Node.js backend, this package helps you build powerful search bars with just a few lines of code.


📦 Installation

npm install wovvmap-search-core
# or
yarn add wovvmap-search-core

✨ Features

  • No External Dependencies: 100% pure TypeScript/JavaScript. Extremely lightweight and fast.
  • Smart Typo Tolerance (Smart Vowel Levenshtein): Automatically forgives spelling mistakes with advanced vowel-aware weightings (e.g., searching "feson" perfectly finds "fashion", but correctly penalizes consonants).
  • First-Letter Strictness & Stricter Prefix Rules: Reduces false positives by 95% by ensuring typos aren't completely random words (e.g., "feson" doesn't falsely match "person", and short words like "food" don't wildly match "footwear").
  • Weighted Fields & Token-wise AND Logic: Give more importance to specific fields. The engine strictly ensures all words typed have some presence across your weighted fields.
  • Advanced Multi-Mode Sorting: Sort results inherently by relevance, asc, desc, or intelligent floor_proximity out-of-the-box.
  • Match Tracing Metadata: Returns exactly which words triggered the search result (perfect for UI Highlighting).
  • TypeScript Support: Full auto-complete and strict type safety directly out of the box.
  • Isomorphic: Runs identically dynamically in the Browser (React, Vue) and on the Server (Node.js).

🚀 Quick Start (For Beginners)

Here is a very simple step-by-step example to get you started in 2 minutes!

1. Prepare your data

Let's say you have an array of objects you want a user to search through.

import { smartSearch } from "wovvmap-search-core";

// Your database or list of products/stores
const myStores = [
  { id: 1, name: "Nike Store", category: "Shoes", tags: ["sports", "running"] },
  { id: 2, name: "Apple Store", category: "Electronics", tags: ["phones", "laptops"] },
  { id: 3, name: "Zara", category: "Clothing", tags: ["fashion", "dresses"] }
];

2. Configure the Search Engine

You need to tell the engine where to look and how important each field is by assigning a weight. Higher weights mean more points!

const options = {
  // Fields to search in your objects
  fields: [
    { path: "name", weight: 10 },        // 'name' is very important (Weight: 10)
    { path: "category", weight: 5 },     // 'category' is less important (Weight: 5)
    { path: "tags", weight: 8, isArray: true } // 'tags' is an array of keywords
  ],
  limit: 10,               // Return a maximum of 10 results
  typoToleranceLevel: 2,   // Typo tolerance level
  includeMeta: true        // Return the exact score and triggered words!
};

3. Run the search

Whenever the user types via an input search bar, just pass that string into the smartSearch function:

const userQuery = "feson"; // Notice the spelling mistake! 

const results = smartSearch(userQuery, myStores, options);

console.log(results);
/* Output automatically identifies the spelling mistake and smartly returns:
[
  { 
    id: 3, 
    name: 'Zara', 
    category: 'Clothing',
    tags: ['fashion', 'dresses'],
    __smartSearch: {
      score: 1250,
      matchedWords: ["fashion"] // Tells your UI exactly what triggered it!
    }
  }
]
*/

🛠 Advanced Options

The SearchOptions object gives you complete control over the engine:

| Property | Type | Default | Description | |----------|------|---------|-------------| | fields | FieldConfig[] | Required | Array defining which object keys to search and their point multiplier (weight). | | limit | number | undefined | Maximum number of matched items to return in the array. | | typoToleranceLevel | number | 2 | Determines how many typos are allowed via Smart Levenshtein logic. 0 means strict exact text mapping only. | | minScore | number | 0 | Minimum score threshold to filter out very weak matches. (Recommended: 10-20 to hide false positives). | | returnAllOnEmpty | boolean | true | If true, returns the entire limit of items when the search text is empty. If false, returns an empty array. | | minSearchCharLength| number| 1 | The minimum number of characters required for a search to trigger. | | includeMeta| boolean| false | If true, search results will include a hidden __smartSearch property containing the match score and matchedWords array! | | sortBy | string | 'relevance' | Determines sorting mode: 'relevance', 'asc', 'desc', or 'floor_proximity'. | | floorSecondarySortBy| string | 'relevance' | Tie-breaker when multiple items are on the exact same floor. 'relevance', 'asc', or 'desc'. | | sortField | string | undefined | The object path to use when sorting asc or desc (e.g., "LocationName.text"). | | activeFloor | number | undefined | The user's current floor. Used contextually when sortBy is 'floor_proximity'. | | floorField | string | undefined | The object path to the floor numerical value (e.g. "z"). |


🎯 Example: Intelligent Floor Proximity Sorting

If your user is inside a mall on Floor 3, you want to show search results for Floor 3 first, then 2, 1, 0, and then floors above them 4, 5.

const options = {
  fields: [{ path: "name", weight: 10 }],
  sortBy: "floor_proximity",
  floorSecondarySortBy: "relevance", // If 2 stores are on Floor 3, show the best keyword match first
  activeFloor: 3, 
  floorField: "floor" // looks for item.floor
};

const results = smartSearch("shoes", myStores, options);

🧠 How the Scoring Works internally

When you search for something, the engine checks every record and awards base points using Token-Wise Exponential Scoring:

  1. Exact Match: Highest Priority (Base multiplier 10,000)
  2. Starts With (Prefix): High Priority (Base multiplier 2,000)
  3. Contains Substring: Medium Priority (Base multiplier 500)
  4. Smart Fuzzy Typos: Exponential Priority. Bad matches get harshly penalized (e.g. 100 points), while near-perfect vowel typos get huge rewards (e.g. 1500+ points).

The base points are then multiplied by the weight you defined for that field. The results are ultimately computed and automatically sorted from highest points to lowest points!

For deeper understanding on the Architecture, Read the HOW_IT_WORKS.md guide.


💡 Pro Tip for React Developers

Use a useMemo hook to run your search so it calculates efficiently and doesn't freeze your UI during re-renders:

const searchResults = useMemo(() => {
   if (!searchText) return myData;
   
   return smartSearch(searchText, myData, options);
}, [searchText, myData]);

Maintained with ❤️ by Wovvmap