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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@wider/registry

v1.0.10

Published

A WIDER foundation component, registering and validating members of other @WIDER public solutions

Downloads

15

Readme

@wider/registry

WIDER modules make significant use of each other. They are published individually as many are of use to the community on a stand alone basis.

The way npm works, it is possible for the same module to be loaded multiple times (same or different versions) from different installed packages within a project and thus if they have what is intended to be working data that spans all activity within the project then the integrity required of a single instance for you thread/cluster is lost. This issue is well documented in chatrooms and is the reason this module was created - to stop it happening or in despair let you know it is happening.

Any module that wants to ensure that it is instantiated only once (per thread/cluster) may invoke this tool which does the following

  • ensures that this tool itself is not loaded multiple times
  • throws an Error.code === "INVALID_MODULE_NAME" if the request does not register a valid module as required for this package to operate
  • detects if the given module has already been loaded and throws an Error.code === "DUPLICATE_CALL" if this is a duplicate.

Errors are logged to the console before being thrown. You can choose to handle the error or let it bubble so that the app exits. All errors have a property called .code which is a programming oriented code if your app wishes to analyse problems.

You can register ES and commonJS modules.

Internally a registry is maintained. You can optionally use this registry as a bundle of your own modules so you only need a single require or import for the bulk of your applications. For commonJS modules you can indicate that they are to be loaded just in time, if and only if they are used. This feature is entirely transparent to your code accessing those modules - it enables you to place large numbers of modules in your package without adverse run time bloat if they are not used.

While there is a small overhead to create a bundle, both you as developer and the runtime processor save time if there are multiple uses of the bundle.

If you have the same problems then this will assist you to identify when the problem arises. Used basically as a registry then you add some lines of code to each module - there is no other impact to your code unless an issue is identified. If you use the advanced features you can avoid using import/require and access your registered modules directly from a cache.

There are reports that are produced in markdown format for you to include in your documentation.

TO COME as separate packages making use of the registry

  • a package builder and publisher that deduces from the registry the dependency order to rebuild packages and publish them to the extent required after your code changes
  • a documentation website builder that integrates the jsDoc components of each of your packages into a solution wide information source

Documentation

Full Documentation

Install

npm install @wider/utils_require

Basic Use

Each module you wish to manage should self register. If the module has not been loaded before then it is added to the list of loaded modules. You can use register.describe_loaded() to get a list of these and also a note of the time from the start of the application that the module load was completed. Place the following code at the start of your module, or at least before it starts to create any side effects.

//ES
import register from "@wider/registry";
const $moduleName = "my-module-name";
register($moduleName);


// commonJS
const register = require("@wider/registry");
const $moduleName = "my-module-name";
register($moduleName);

Soft registration

With this mode, you do not add the registry to your dependencies at all nor do you import or require it (ie you skip the first line in each example above). Your module package can be distributed without any dependency to this package. If another package loads the registry, such as the applications main module, then your package will register - otherwise nothing happens. Put this at the very start of your code

process.nextTick(()) => { if (global.$wider) global.$wider.registry.register( $moduleName )};

Advanced use

With advanced use, you also provide your object that is being registered and may choose to influence where how is cached and accessed. We illustrate creating the object using require but any means may be used to create the value to be processed including import for es modules

module.exports = whatEverYouCreated;
whatEverYouCreated.$moduleName = "somethingOrOther"; // what another package would use require or import to get this module
whatEverYouCreated.$objectName = "sOO"; // the name you or others generally use to refer to the default or primary exported component

const $wider = register.bundle(whatEverYouCreated); // gives you $wider.somethingOrOther

The dictionary $wider will contain at least $wider.register and $wider.sOO. The $wider object will acquire new members as new objects are registered.

You may choose to save your object in a specific section in the repository so as to maintain an orderly structure. But please note that you cannot by error use multiple sections to cause the same module to be loaded into different locations

const $wider = register.bundle(whatEverYouCreated, "nameOfMySection");

This give you $wider.nameOfMySection.sOO

Registering third party modules

If importing or requiring other modules, you should leave it to them to register themselves if they are under your control - you can just require or import them or access them through the registry.

If however they are third party objects, then they won't have registered themselves. If you wish them to be registered, then you can call registry.register() as their proxy. Provided you ensure that you do not try and register the same module twice (throws an error, you can check in $wider) you may use the various methods already given.

You may also submit an array of objects to be submitted as a bundle, here illustrated some code internal to the registry - so these items are always registered for you and you can simply use them.

// load or import these objects and ensure each one has a property (preferably not enumerable) called $moduleName and then ...

global.$wider.registry.bundle([Module, Require, fs, path, whereAmI]);

In this mode, the registry constructs the $objectName if it is not provided. You can find out what value is used using the .describe_...() methods. If you do not like the guesses we make as to these values then set them yourself as required in each object.

Deferring load

Deferred load modules are loaded just in time if your application makes use of them. This is transparent to your code. ES modules will not import synchronously but this is necessary to maintain transparency to your code. So you may not defer any ES modules. You may however defer JSON objects, and other objects loadable via @wider/utils_require extensions such as markdown, xml, and other objects.

Defer is used similarly to .bundle() except you provide module names as used by .require(). If your object does not provide an .$objectName then you can provide it. The example shows both ways.

const myXMLprocessor = {
    $moduleName : "saxon-js",
    $objectName : "SaxonJS"
}

global.$wider.registry.bundle(["@wider/utils_markup", myXMLprocessor]);

Merging a load

With merge, the members of the object you provide will generate additional properties to the pre-existing object already registered. If the pre-existing object is deferred, it will first be loaded so that the new properties can be added to it.

Merge cannot overwrite properties that are already present. In the recipient object, it creates enumerable immutable readonly getters that return the same named property/method in your supplied merge object.

This means that your methods in your merge objects may continue to update other merged properties it provides, and these will be seen via the recipient object, but access via the recipient object cannot modify them

Properties .$moduleName, $objectName, and $register are never merged.

Your recipient module will be found regardless of the section it is filed in

const recipient = "somethingOrOther"; // your recipient object's $moduleName

const registry = $wider.registry;
// define something or other extension
const sOOE = [
    addition1: {...something1...},
    addition2: {...something2...}
];

// add the SOOE members to sOOname
registry.merge(sOOE,  recipient)

This might result in

$wider
    .somethingOrOther
        .initialEntry1
        .initialEntry2
        .addition1
        .addition2

Summary of Features

  • registry.register() the full featured do it all yourself version - generally it is easier to use the other methods
  • registry.bundle() act as proxy to submit a bundle of other packages that do not register themselves
  • registry.defer() as * registry.bundle() except that you provide package names and these are not required/loaded into memory individually unless and until actually used - only supports commonJS modules
  • registry.merge() merge new properties into an existing registered bundle
  • registry.find() given a moduleName retrieves its object
  • registry.describe_loaded() a markdown like string documenting the registered modules and their access points
  • registry.describe_published() a markdown like string documenting the top level structure of $wider and its sections.
  • registry.DICTIONARY a symbol that can be used as the value of property .$register in a plain object to mark it as containing documentable properties when seen via registry.describe_published(). Used as a property value in javascript { $registry: registry.DICTIONARY} or in a json file as { "$registry": "DICTIONARY" }
  • registry.ROOT can be used as the moduleName for the root (ie not a section) level of @wider.