0.1.5 • Published 4 years ago

@mattriley/module-initialiser v0.1.5

Weekly downloads
-
License
-
Repository
-
Last release
4 years ago

module-composer

Composes 'modules' enabling coarse-grained module-level depenency injection.

A module in this sense is any plain object with a __modulename entry. Any entries containing functions are invoked with a given object argument. The object argument is assigned the current module named after __modulename. Any entries not containing functions are traversed and returned as-is unless __modulename is present.

Install

npm i module-composer

Usage

const compose = require('module-composer');
const modules = require('./modules');
const moduleB = compose(modules.moduleB, {});
const moduleA = compose(modules.moduleA, { moduleB });

Example

Take the following object graph:

const modules = {
    moduleA: {
        foo: ({ moduleA, moduleB }) => () => {
            console.log('foo');
            moduleA.bar();
        },
        bar: ({ moduleA, moduleB }) => () => {
            console.log('bar');
            moduleB.baz();
        }
    },
    moduleB: {
        baz: ({ moduleB }) => () => {
            console.log('baz');
            moduleB.qux();
        },
        qux: ({ moduleB }) => () => {
            console.log('qux');
        }
    }
};

Upon composition, and invocation of foo, the intended output is:

foo
bar
baz
qux

Here's how these modules might be composed manually:

const moduleB = {};
moduleB.baz = modules.moduleB.baz({ moduleB });
moduleB.qux = modules.moduleB.qux({ moduleB });

const moduleA = {};
moduleA.foo = modules.moduleA.foo({ moduleA, moduleB });
moduleA.bar = modules.moduleA.bar({ moduleA, moduleB });

moduleA.foo();

Here's how these modules might be composed with module-composer:

const compose = require('module-composer');

const modules = {
    moduleA: {
        __modulename: 'moduleA',
        foo: ({ moduleA, moduleB }) => () => {
            console.log('foo');
            moduleA.bar();
        },
        bar: ({ moduleA, moduleB }) => () => {
            console.log('bar');
            moduleB.baz();
        }
    },
    moduleB: {
        __modulename: 'moduleB',
        baz: ({ moduleB }) => () => {
            console.log('baz');
            moduleB.qux();
        },
        qux: ({ moduleB }) => () => {
            console.log('qux');
        }
    }
};

const moduleB = compose(modules.moduleB, {});
const moduleA = compose(modules.moduleA, { moduleB });

moduleA.foo();

How is this useful?

The above example could be broken down into the following directory structure:

proj/
    run.js
    src/
        index.js
        module-a/
            index.js
            foo.js
            bar.js            
        module-b/
            index.js  
            baz.js
            qux.js                  

proj

// run.js

const compose = require('module-composer');
const src = require('./src');

const moduleB = compose(src.moduleB, {});
const moduleA = compose(src.moduleA, { moduleB });

moduleA.foo();

proj/src

// index.js

module.exports = {
    __modulename: 'src',
    moduleA: require('./module-a'),
    moduleB: require('./module-b')
};

proj/src/module-a

// index.js

module.exports = {
    __modulename: 'moduleA',
    foo: require('./foo'),
    bar: require('./bar')
};


// foo.js

module.exports = ({ moduleA, moduleB }) => () => {
    console.log('foo');
    moduleA.bar();
};


// bar.js

module.exports = ({ moduleA, moduleB }) => () => {
    console.log('bar');
    moduleB.baz();
};

proj/src/module-b

// index.js

module.exports = {
    __modulename: 'moduleB',
    baz: require('./baz'),
    qux: require('./qux')
};


// baz.js

module.exports = ({ moduleA, moduleB }) => () => {
    console.log('baz');
    moduleA.qux();
};


// qux.js

module.exports = ({ moduleA, moduleB }) => () => {
    console.log('qux');
};

Couldn't those index.js files be generated?

Glad you asked. Absolutely. See: https://github.com/mattriley/node-indexgen