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

@4i4/registry

v1.0.0

Published

Simple Registry class

Readme

Registry

You can create your own registry of any kind, separate the items in the registry by scopes, and search by multiple suggestions.

Why not use a simple object?

In the end this registry is just normal object that contains key:value pairs separated by scopes.

The need to search by multiple suggestions.

This "tool" was created by the needs of a project that was storing all rendable components that has as templates (paths to the components) in a single object. Each rendable item of the project can use multiple templates depending on a context and if a template is missing for the special context it can use the closest or a default one.
So the suggestion search was created as function.

The need for better maintenance.

With the extending the project the templates has multiply and the object was getting bigger and difficult to maintain. To skip duplication of the template names we introduced one more level of the object - we separated the templates by scopes. That made the object event longer. We needed a way to update the object as easy as can be and to keep it in order.
So the set function was created.

The need for consistency.

With one successful usage of this template registry the requests for new projects with same functionality was growing. Now we needed to maintain not only one object in a single project, but multiple objects in multiple projects. Updating a single project with a new functionality or fixing a bug for it meant that we need to go through all the projects.
So the registry "tool" was in order to be created.
And once we had it, we found multiple cases outside the template registry that we could to use it.

Pros & Cons

Pros:

  • search by multiple suggestions
  • easy to maintain big objects
  • easy to separate items by scopes

Cons:

  • one more library to install

Installing:

Using npm:

$ npm install @4i4/registry

Using yarn:

$ yarn add @4i4/registry

Using pnpm:

$ pnpm add @4i4/registry

Methods:

Constructor

Params

| Param | Type | Optional | Default value | Description | |-----------------|----------|--------------|-------------------|------------------------------------------| | data | object | Yes | {} | Predefined registry data. | | default_scope | string | Yes | _ | The default scope. Default value is _. |

Example

const data = {
  // Each scope is an object of key:value pairs
  "scope_1": {
    "key_1": "value_1",
    "key_2": "value_2"
  },
  "scope_2": {
    "key_3": "value_3",
    "key_4": "value_4"
  }
};

const registry_1 = new Registry();
const registry_2 = new Registry(data);
const registry_3 = new Registry(data, "scope_1");

.set

Params

| Param | Type | Optional | Description | |-----------|----------|--------------|----------------------------------------------------------------| | key | string | No | The key for the item. | | item | any | No | The item it self. | | scope | string | Yes | The scope in which this pair of key:value will be assigned to. |

Example

registry.set("key_1", "value_1");
registry.set("key_2", "value_2", "scope_1");

.get

Params

| Param | Type | Optional | Description | |-----------------|----------|--------------|----------------------------------------------------| | key | string | No | The key for the item. | | default_value | any | Yes | Return this value if the item is missing. | | scope | string | Yes | The scope in which this key will be retrieve from. |

Example

const key_1 = registry.get("key_1");
const key_2 = registry.get("key_2", "default_value_2");
const key_3 = registry.get("key_3", null, "scope_1");

.getAll

Params

| Param | Type | Optional | Description | |-----------------|----------|--------------|-----------------------------------------------------------------------------------------------| | scope | string | Yes | Retrieve all items from this scope. If non provided the whole registry data will be returned. |

Example

const registry = new Registry({
  "scope_1": {
    "key_1": "value_1",
    "key_2": "value_2"
  },
  "scope_2": {
    "key_3": "value_3",
    "key_4": "value_4"
  }
});

const scope_1 = registry.getAll("scope_1");
const data = registry.getAll();

// This will print { "key_1": "value_1", "key_2": "value_2" }.
console.log(scope_1);
// This will print { "scope_1": { "key_1": "value_1", "key_2": "value_2" }, "scope_2": { "key_3": "value_3", "key_4": "value_4" }}.
console.log(data);

.clone

Example

const registry_1 = new Registry();
const registry_2 = registry_1.clone();

Typescript:

Simple:

import Registry from "@4i4/registry";

const registry = new Registry<string | number | boolean>();

registry.set("string_value", "This is example of string");
registry.set("number_value", 300);
registry.set("boolean_value", false);

Use predefined data:

import Registry, { RegistryType } from "@4i4/registry";

const data: RegistryType<string | number | boolean> = {
  "scope_1": {
    "string_value": "This is example of string",
    "number_value": 300,
    "boolean_value": false
  }
}

const registry = new Registry<string | number | boolean>(data);

Examples:

Simple:

import Registry from "@4i4/registry";

const settings = new Registry();

settings.set("site_name", "This is the name of the site");
settings.set("homepage", "/home");
settings.set("languages", { "en": "English", "de": "Deutsch" });

const siteName = settings.get("site_name");
const languages = settings.get("languages");

Using the scopes:

import Registry from "@4i4/registry";

const settings = new Registry();

// This setting is part of the default scope.
settings.set("cache_enabled", false);
// Next two settings are part of scope "site_info".
settings.set("site_name", "This is the name of the site", "site_info");
settings.set("homepage", "/home", "site_info");
// Next two settings are part of scope "languages".
settings.set("en", "English", "languages");
settings.set("de", "Deutsch", "languages");

// Retrieve setting from the default scope.
const isCacheEnabled = settings.get("cached_enabled");
// Retrieve setting from scope "site_info".
const siteName = settings.get("site_name", "", "site_info");
// Retrieve all settings from scope "languages".
const languages = settings.getAll("languages");

Use predefined data:

import Registry from "@4i4/registry";

const data = {
  "site_info": {
    "site_name": "This is the name of the site",
    "homepage": "/home"
  },
  "languages": {
    "en": "English",
    "de": "Deutsch"
  }
};
// Creating new registry with two custom scopes - "site_info", "languages"
const settings = new Registry(data);
// This setting is part of the default scope.
settings.set("cache_enabled", false);

const siteName = settings.get("site_name", "", "site_info");

Changing the default scope:

import Registry from "@4i4/registry";

const data = {
  "site_info": {
    "site_name": "This is the name of the site",
    "homepage": "/home"
  },
  "languages": {
    "en": "English",
    "de": "Deutsch"
  }
};
// Set the default scope to "site_info"
const settings = new Registry(data, "site_info");

// This setting will be assinged to the default scope - "site_info".
settings.set("description", "This is the description of the site");
// Retrieve setting from the default scope - "site_info".
const siteName = settings.get("site_name");

Retrieve single settings from multiple suggestions:

import Registry from "@4i4/registry";

const data = {
  "page": {
    "title": "This is the default page title",
    "title-tablet": "This is the tablet page title"
  }
}
// Set the default scope to "page"
const settings = new Registry(data, "page");

// Search for one of the following settings. 
const search = ['title', 'title-tablet', 'title-mobile'];
// This will retrieve the last found item from the search array.
const pageTitle = settings.get(search);
// This will print the tablet title. 
console.log(pageTitle);

Cloning the registry:

import Registry from "@4i4/registry";

const data = {
  "site_info": {
    "site_name": "This is the name of site 1",
    "homepage": "/home"
  },
  "languages": {
    "en": "English",
    "de": "Deutsch"
  }
};
// Set the default scope to "site_info"
const site_1 = new Registry(data, "site_info");
const site_2 = site_1.clone();

site_2.set("site_name", "This is the name of site 2");

const siteName1 = site_1.get("site_name");
const siteName2 = site_2.get("site_name");

// This will print "This is the name of site 1"
console.log(siteName1);
// This will print "This is the name of site 2"
console.log(siteName2);