Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

moog-require

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

moog-require

moog-require extends moog with support for type definitions in local files and npm modules.

  • 0.1.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
111
decreased by-1.77%
Maintainers
1
Weekly downloads
 
Created
Source

Build Status

moog-require

moog-require provides powerful module subclassing for server-side development. It extends the features of moog with the following additions:

  • Fetches modules from a local modules folder if they are not defined explicitly
  • If a module is defined explicitly and also exists in localModules, the local modules folder becomes a source of defaults for properties not defined explicitly
  • Fetches modules from npm if they are not defined either explicitly or via the local modules folder
  • If a module exists by the same name both in npm and via explicit definition or local modules, automatically extends the npm module without the need for a new name (like the "category" feature of Objective C)
  • Provides access to an "asset chain" of subclass module directories and type names, to implement template overrides and the like
  • Also supports bundling moog modules in a single npm module, if explicitly configured

Example


// IMPLICIT BASE CLASS OF ALL MODULES
// (if configured - see app.js below)
//
// In node_modules/module/index.js

module.exports = {
  self.construct = function(self, options) {
    self.renderTemplate = function(name, data) {
      var i;
      for (i = 0; (i < options.__meta.length); i++) {
        var meta = options.__meta[i];
        var path = meta.dirname + '/views/' + name + '.html';
        if (fs.existsSync(path)) {
          // Deepest subclass wins
          return templateEngine.render(path, data);
        }
      }
    };

  };
};

// NPM MODULE
//
// In node_modules/events/index.js

module.exports = {
  color: 'red',

  construct: function(self, options) {

    self.defaultTags = options.tags;

    self.get = function(params, callback) {
      // Go get some events
      return callback(events);
    };
  }
}

// PROJECT LEVEL SUBCLASS OF NPM MODULE
//
// in lib/modules/events/index.js
module.exports = {
  color: 'green',

  construct: function(self, options) {
    var superGet = self.get;
    self.get = function(params, callback) {
      // override: only interested in upcoming events
      params.upcoming = true;
      return superGet(params, callback);
    };
  }
};

// in app.js

var synth = require('moog-require')({
  localModules: __dirname + '/lib/modules',
  defaultBaseClass: 'module'
});

synth.define({

  // SETTING A DEFAULT OPTION THAT APPLIES TO *ALL* MODULES
  // (because we're setting it for the defaultBaseClass)
  'module': {
    color: 'gray'
  },

  // CONFIGURATION (IMPLICIT SUBCLASS) OF A PROJECT-LEVEL MODULE
  // (same technique works to configure an npm module)

  'events': {
    color: 'blue',
    // More overrides in lib/modules/events/index.js (above).
    // Anything here in app.js wins
  },

  // EXTENDING A PROJECT-LEVEL MODULE TO CREATE A NEW ONE
  'parties': {

    // Let's subclass a module right here in app.js (usually we'd just
    // set site-specific options here and put code in
    // lib/modules/parties/index.js, but you're not restricted)

    extend: 'events',
    color: 'lavender',

    // Let's alter the "tags" option before the
    // base class constructors are aware of it

    beforeConstruct: function(self, options) {
      options.tags = (options.tags || []).concat('party');
    },

    // This constructor can take a callback, even though
    // the base classes don't. You can mix and match

    construct: function(self, options, callback) {
      // options.color will be lavender
      var superGet = self.get;
      self.get = function(params, callback) {
        // override: only interested in parties. Let's
        // assume the base class uses this as a query
        params.title = /party/i;
        return superGet(params, callback);
      };

      // Output names and full folder paths of all modules in the
      // subclassing chain; we can use this to push assets and
      // implement template overrides
      console.log(options._directories);
    },

    setBridge: function(modules) {
      // Do something that requires access to the
      // other modules, which are properties of
      // the modules object
    }
  }
});

// Instantiate all the modules, passing in some
// universal options that are provided to all of them. This
// only instantiates modules mentioned in `definitions`, but
// they may override or subclass modules in npm or the
// project-level modules folder

return synth.createAll({ mailer: myMailer }, function(err, modules) {
  return modules.events.get({ ... }, function(err, events) {
    ...
  });
});

// We can also tell the modules about each other. This
// invokes the setBridge method of each module, if any,
// and passes the modules object to it

synth.bridge(modules);

// We can also create an instance of any module at any time,
// and pass it additional options. This is useful if you are
// not following the singleton pattern. We don't promise
// killer performance if you create thousands of objects
// per second

return synth.create('parties', { color: 'purple' }, function(err, party) {
  ...
});

Calling require yourself

Don't.

Well, okay...

If you want to write this:

`extend': require('./lib/weird-place/my-module/index.js')

You may do so, but in that case your module must export its __name, __dirname and __filename, like so:

module.exports = {
  __name: 'my-module',
  __dirname: __dirname,
  __filename: __filename,
  construct: function(self, options) { ... }
};

This is only necessary if you are using require directly. Most of the time, you will be happier if you just specify a module name and let us require it for you. This even works in npm modules. (Yes, it will still find it if it is an npm dependency of your own module.)

Packaging multiple moog-require modules in a single npm module

Sometimes several modules are conceptually distinct, but are developed and versioned in tandem. In these cases there is no benefit from separate packaging, just a significant delay in npm install. npm peer dependencies are one way to handle this, but npm peer dependencies may be on the chopping block, and they are significantly slower than pre-packaging modules together.

The difficulty of course is that the link between npm module names and moog-require module names is broken when we do this. So we need another way to indicate to moog-require that it should look in the appropriate place.

Since searching for "X", where X is actually provided by module "Y", is not a core feature of npm itself we have kept this mechanism simple: you can give moog-require an array of npm module names that contain a "bundle" of definitions rather than a single definition. An npm "bundle" module then must export a moogBundle array property which contains the names of the moog-require modules it defines. The actual definitions live in lib/modules/module-one/index.js, lib/modules/module-two/index.js, etc. within the bundle npm module. moog-require will find these automatically and will consider these first before requiring normally from npm.

Here's an example:

// In node_modules/mybundle/index.js

module.exports = {
  moogBundle: {
    modules: [ 'module-one', 'module-two' ],
    directory: 'lib/modules'
  }
};

// In node_modules/mybundle/lib/modules/module-one/index.js

module.exports = {
  construct: function(self, options) { ... }
};

// In node_modules/mybundle/lib/modules/module-two/index.js

module.exports = {
  construct: function(self, options) { ... }
};
// In our application

var synth = require('moog-require')({
  bundles: [ 'mybundle' ],
  localModules: __dirname + '/lib/modules',
  defaultBaseClass: 'module'
});

synth.define({
  'module-one': {},
  'module-two': {}
});

Note that just as before, we must include these modules in our explicit define calls if we want to instantiate them with createAll, although we don't have to override any properties; we can pass empty objects to just use the defaults defined in the project level folder, and/or implicitly inherit from npm.

However, you may explicitly create a type that exists only in the project level folder and/or npm.

Changelog

0.1.0: compatible with moog 0.1.0 in which the __meta property became an object with chain and name properties.

Keywords

FAQs

Package last updated on 06 Feb 2015

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