New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

r42

Package Overview
Dependencies
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

r42

Dependency injection done right.

  • 0.4.0
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

r42

Mix in node's require, some angular dependency injection look&feel and the ease of use of RequireJS and what do you get?

Dependency injection done right for Node.js!

WARNING

There are breaking changes between the 0.2.0 branch and the 0.3.0 branch. Updating your code will be mandatory.

Getting started

Installation
npm install r42
Your first module

Let's code lib/toto.js :

// path & fs are examples to show you how to load node modules
// _ will contain lodash (see next section to see why)
define(function (path, fs, _, dep1, dep2) {
  /* Your code goes here */

  // You can export anything, a scalar, a function, an object, an array...
  // Objects & functions should be preferred
  return /* what you exports goes here */;
});
Configuring & lauching your project
var r42 = require('r42');
var path = require('path');

var context = r42.config({
  // Sets the root directory in which modules are looked for
  baseDir: path.join(__dirname, 'lib'),

  // Allows to map paths / module names to something else
  paths: {
    // _ will load lodash
    _: 'lodash',

    // Target paths are all relative to baseDir.
    // Here "library" will try to load "baseDir + '../vendor/library'"
    library: '../vendor/library',

    // Replacement in paths are also possible: here all modules named
    // 'sub/.../truc' will be looked for into the ../sub folder
    sub: '../sub',

    // Alias can also be used in configuration but they HAVE TO be declared
    // BEFORE being used in the object
    shMod: 'sh/module', // refers to 'sh/module'
    sh: 'shortcut',
    shMod2: 'sh/module2', // refers to 'shortcut/module2'
  },
});

// Let's get started
context.inject(function (toto) {
  // you can use your dependency here
});
More complex dependencies
Module in subfolders

If you want to resolve complex names in subdirectories, you can use the optional replacer argument of the define function. Here is an example:

define({
  test: 'sub/folder/test',
}, function (test) {
  // here test will be resolved to module 'sub/folder/test'
});

The object maps an argument's name to the real module name locally. The argument name will be replaced by the given module name before injection happens.

You can also use special r42 comments (looking like /*! module */) before your argument names:

define(function (/*! sub/folder/test */ test) {
  // here test will be resolved to module 'sub/folder/test'
});

Note : spaces are optional in r42 comments.

Modules in the same folder

Sometimes, it is a pain to refer to a module in the same folder as you are right now. r42 allows for a fine way to do so.

Using $ to prefix your variable's name will automatically cause r42 to replace it by your current module's "path". It also works to prefix files in the replacer object.

In a module module/toto.js:

define({
  superSub: '$super/sub',
}, function (superSub, $sideFn, /*! $sub/sideValue */ sideVal) {
  // superSub refers to 'module/super/sub'
  // $sideFn refers to module/sideFn
  // sideVal refers to $sub/sideValue
});
Special case : index.js in a subfolder

You can refer to an index module using only the folder's name just like so:

In file folder/index.js:

define(function () {
  return {
    answer: 42
  };
});

And in a file at the same level as folder:

define(function ($folder) {
  // Here $folder will load folder/index.js
});
Circular dependencies

Those are working "automatically" but you NEED to exports barebone objects on both modules for it to work.

Here is an example:

In a module a.js:

define(function (b) {
  // here b might be empty if it was loaded before a, so don't use it

  return {
    aFn: function () {
      // here b should be fully usable
      b.bFn();
    },
  };
});

In a module b.js:

define(function (a) {
  // here a might be empty if it was loaded before b, so don't use it

  return {
    bFn: function () {
      // here a should be fully usable
      a.bFn();
    },
  };
});
Other load mechanism

r42 allows you to create your own loading modules & to load modules using a different policy than its own. By default, a require load mechanism & a json load mechanism are included by default in r42.

To use a different load mechanism than the default one, you need to prefix its name by plugin! (eg: require!module or json!module). This implies that you have to use the replacer argument or r42 comments to load a plugin using a specific loader.

Examples:

With the json loader:

define(function (/*! json!$config */ config) {
  // Here "config" contains ./config.json parsed into a JS structure
});

With the require loader:

define(function (/*! require!$externalModule */ externalModule) {
  // Here "externalModule" contains the value returned by calling require with
  // ./externalModule
});
Special APIs
Loading modules dynamically

You can also use r42.inject to load modules dynamically. In this case, provide a module name or module list and optionally a replacer as usual. Here is what it could look like:

In module dynamic.js

define(function (r42) {
  // This will load lodash in variable _.
  var _ = r42.inject('lodash');
  // Same thing for the variable alias but using the replacer argument.
  var alias = r42.inject({ alias: 'lodash' }, 'alias');

  // An example with multiple load at once
  // Here modules[0] will resolve to require('util')
  // and modules[1] to require('net')
  var modules = r42.inject(['util', 'net']);

  // You can also use the replacer argument with an array:
  // this example will load the same modules as the previous one
  modules = r42.inject({a: 'util', b: 'net'}, ['a', 'b']);
});
Writing your own loader plugin

You can write other loader plugins and register them to r42 to use them after that in your codebase. Here is how to do so:

var r42 = require('r42');
var path = require('path');
var fs = require('fs');
var myYamlModule  = require('myYamlModule');

r42.registerLoader('yaml', function (moduleDef, parent, mc) {
  // moduleDef contains information about the module that should be loaded
  // parent contains information about the module that required moduleDef
  // mc is the context object, it handles the modules' cache

  // mc.$baseDir is the root path of the project
  // moduleDef.name contains the path to the module from baseDir
  // (without any extension)
  var filePath = path.join(mc.$baseDir, moduleDef.name + '.yaml');

  try {
    // The loading should be synchronous
    var yaml = fs.readFileSync(filePath, 'utf8');
    yaml = myYamlModule.parse(yaml);

    // Init the module into the context
    mc.initModule(moduleDef, yaml);
  } catch (e) {
    // <module>.fullName contains the plugin's name + ! + the module's name
    e.message = '[r42:yaml] Cannot load module ' + moduleDef.fullName +
      ' (required by module ' + parent.fullName + '): ' + e.message;
    throw e;
  }
});
Printing dependencies

This function might be useful to gather information about your module & to debug dependencies problems. It takes an options parameter which is an object that can take the following two options:

  • colors (defaults to true): whether to colorize the output or not
  • print (defaults to true): whether to print to stdout automatically the result or not

WARNING: The colors option requires that you install chalk (version >=0.4.0) as a dependency of your project.

It returns a string containing the dependencies information.

var r42 = require('r42');

var context = r42.config({
  // Your config HERE
});

// Let's get started
context.inject(function (/* Your dependencies */) {
  // Dump dependencies with colors using process.stdout.print
  context.dumpDeps();

  // This verion will return you the string without any colors and without printing it :
  var depstr = context.dumpDeps({
    colors: false, // Do not use term colors in the output string
    print: false,   // Do not print the string on stdout
  });
  // Now you can do whatever you want with the string, like send it over network...
});

Using r42 in libraries

Since version 0.0.21, r42 has been rewritten to be completely synchronous. This means that you can use it easily, even to create library packages. Here is a simple example of what your main library file might look like :

var r42 = require('r42');
var context = r42.config(/* Your configuration object */);

context.inject(function (/* Your dependencies */) {
  module.exports = {
    // Whatever
  };
});

Changelog

0.4.0
  • Add plugin API
  • Add plugins
    • default (previous loading mechanism moved to a plugin)
    • require (force use of require, no define expected in module)
    • json (load JSON file - using require)
0.3.1
  • Remove the beta channel warning that was forgotten
0.3.0
  • Make r42 instantiable.
  • Clean up related require's cache after loading a module with r42
0.2.2
  • Continue work started with 0.2.1 to prepare for 0.3.0
0.2.1
  • Change architecture to prepare for 0.3.0 that will change r42 API so that r42 si not a singleton anymore
0.2.0
  • Colors dependency was dumped in favor of chalk that does not mess up String's prototype
  • dumpDeps
    • small bug fixes
    • better readability

Upcoming changes

  • Add a test API

Keywords

FAQs

Package last updated on 04 Feb 2014

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc