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

@equinor/echo-search

v3.0.0

Published

![logo](https://raw.githubusercontent.com/equinor/EchoCore/main/doc/ee.png)

Readme

echo-search

logo

This library was generated with Nx.

⚠️ Dependency Rules

Source of truth: /eslint.config.js - The @nx/enforce-module-boundaries rule defines all allowed dependencies.

echo-search can only import from:

  • echo-core
  • echo-base
  • echo-utils

echo-search CANNOT import from:

  • echo-framework
  • echo-components
  • echopedia-web (app) ❌

echo-search worker CANNOT import from any echo-lib

It needs to be self-contained, as it needs to run independently from the rest of the application. We experienced in the past, that echo-search as a standalone lib (built with rollup) fails to start the webworker if it imports any code from any echo lib.

See libs/README.md for the full dependency flow diagram.


What's new?

Changelog

Developer Readme

Developer Documentation

Echo Search uses web workers! Read more about them in the above mentioned developer readme.

Use Echo Search

Install

Add EchoSearch as peer dependency. There should only be one instance of the search module, instantiated by echo-inField.

npm install @equinor/echo-search --save-dev

Copy this to peer-dependencies, to make it available through echo-inField.

Features

Search

  • Search in offline data if available: better search results than online search. We search in more properties, and try to sort it by best match.
  • Most data types fallback to online search if offline search is not available. SAP data only have offline search.

Comlink (threading)

  • All logic runs in it's own thread, to avoid hogging the main thread.
  • Main-thread -> EchoSearchWorker -> Search/Sync-thread
  • Can be commented out for debugging (run all in main thread when debugging). See EchoWorkerInstance

Data Verification and Correction

  • Verify that we have the expected data count, checked against backEnd. Re-download if we are missing a lot (less than 90%). A system might be down in STID when we download the tags, and we'll get all tags except this system. We don't have any way of knowing this when we get the tags, so that's why we have this data verification and full re-sync.
  • The data types will also do a full re-download on a scheduled basis. Small/quick data amount will run often, slow data types as TAG more seldom. The reason is because we cannot guarantee we have the latest data. We try to get all updated items, but sometimes the APIs fail to provide us with the correct information. ProCoSys doesn't give us sub-data, so all tag info on checklists are missing for example. We've also seen other APIs giving wrong information now and then because of bugs. That's why we re-download everything now and then.

Strict Date type interfaces

  • The interfaces have a strict type definition. Optional type SHOULD be specified if it can be undefined.
  • Data type checking: we clean up data/data types we get from the api. String-Dates are converted to dates, string-numbers to numbers, etc.
  • Unwanted data is also stripped away, to save memory.

Architecture

  • Main/Echo-Module -> Index -> (Main-thread) -> EchoSearchWorker -> (Search-thread) -> External -> Data (Sync or Search)
flowchart LR

Main/Echo-Module --> Index --> |Main-thread| EchoSearchWorker --> |Search-thread| K[External]
K --> Sync
K --> Search

Usage

The data sources that are already exposed for search use in the other modules are:

  • Tags
  • Tag Details
  • Notifications
  • Work Orders
  • Punches
  • Checklists
  • CommPacks
  • McPacks

The data sources to be added:

  • Documents

You can use the data sources from Echo in the modules by writing Search, the data source you want, and the function that is needed to extract. For instance, to get all the local tags use:

const result = Search.DataSource.Function(...)

const tagsResult = Search.Tags.getAllAsync(["tagNo1", "tagNo2"])

if(!tagsResult.isSuccess)
{
    console.error(tagsResult.error)
}

Result & Error handling

All functions will return the result object, where isSuccess is true if the call was successful.

Result represents the result of a void function, which contains the error if isSuccess is false.

export interface Result {
    readonly isSuccess: boolean;
    readonly error?: SearchModuleError;
}

ResultValue is used for single value result. IsNotFound flag will be true if the search didn't find anything.

export interface ResultValue<T> extends Result {
    readonly value?: T;
    isNotFound: boolean;
}

ResultArray is used for single value result. Empty array indicates not found.

export interface ResultArray<T> extends Result {
    readonly values: T[];
}

And the error interface

export interface SearchModuleError {
    readonly type: SyncErrorType;
    readonly name?: string;
    readonly message?: string;
    readonly stack?: string;
    readonly httpStatusCode?: number;
    readonly url?: string;
    readonly properties?: Record<string, unknown>;
}

resultHelper

resultHelper can be used for converting SearchModuleError interface object to the Error class object, as well as throwing this error if needed. There is also a few helper functions like isForbiddenError and isNotFoundError.

export const resultHelper = {
    toBaseError,
    throwIfError,
    throwIfErrorIgnoreNotFound,
    isForbiddenError,
    isNotFoundError
};

More Examples:

const tagsResult = Search.Tags.searchAsync("RNG-TAG-01234");
resultHelper.isNotFoundError(tagsResult);
export async function searchForClosestTagNo(tagNo: string): Promise<string | undefined> {
    const result = await Search.Tags.closestTagAsync(tagNo);
    resultHelper.throwIfErrorIgnoreNotFound(result); //surface any api errors to the top error handler
    return result.value;
}

Running unit tests

Run nx test echo-search to execute the unit tests via Jest.