@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.

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.

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
  • detects if the named 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.

Documentation

Full Documentation

Install

npm install @wider/utils_require

Basic Use

//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. Your module package can be distributed without the overheads. If another package loads the registry, such as the applications main module, then your package will register. Put this at the very start of your code

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

This approach is assured with es modules. If you are running commonjs modules

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.

const $moduleName = "somethingOrOther";
const sOO = require($moduleName);
const $wider = register($moduleName, sOO); // gives you $wider.somethingOrOther

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

If you use @wider/utils_bundler, those objects will also be registered and appear within $wider. In this case, the objects can be configured to be loaded just in time if they are actually used - thus allowing you to create a large registry but without the overheads of all the entries being loaded into memory.

You may choose to save your object in a specific section in the repository so as to maintain an orderly structure.

const $wider = registry.register($moduleName, sOO, "sOOname"); // gives you $wider.sOOname;
const $wider = registry.register($moduleName, sOO, "sOOname", "mySection"); // gives you $wider.mySection.sOOname;

Using imported or required modules

If imported or require other modules, you should leave it to them to register themselves. 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

registry.register([module1, module2, module3 ...]);  //loaded them at the top level
registry.register([module1, module2, module3 ...], null, null, "mySection") // loads them into the named section

To use this approach, each module must at least have the property $moduleName and optionally the property $objectName. If they are absent,most foreign objects will accept you injecting these values so you can then register the object or you can wrap them in a container.

Supplementary Properties

  • 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
  • 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() an markdown like string documenting the top level structure of $wider and its sections.
  • registry.DICTIONARY a symbol that can be used 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. Use with care as using this increases the risks of name conflicts with later releases.
const $moduleName = "somethingOrOther";

// register as previous example

const registry = $wider.registry;
const sOOE = [
    addition1: {...something1...},
    addition2: {...something2...}
];

// add the SOOE members to sOOname
registry.bundle(sOOE,  "sOOname")

This might result in

$wider
    .sOOName
        .initialEntry1
        .initialEntry2
        .addition1
        .addition2