Components (Business Layer) #

As was said below, components are special ifnode framework item for describing business logic of application. Each component has access to lower parts from ifnode application hierarchy and can using them for resolving problem.

Each component can be presented by singular script file or by folder with component parts. In general, folder component must have index.js file which will be "face" of component and all others parts from folder will used only by internal component definitions. Situation with several logically independent parts in component requires to decompose it to single role components. Also component must follow SOLID principles for more clear defining.

Components can use other components by app.component method.

Initializing #

All components placed in special project folder by default it a protected/components. ifnode framework automatically read components directory when one of app.load or app.run (deprecated) methods will be invoked. Framework loads components by node.js require from this folder only from first level of internal directories.

Each component can be presented by one of definition types:

  1. Component class
  2. Component class instance
  3. app.Component deprecated
  4. Non-Component class
  5. Primitive value

Component class #

Component presented by class which must be inherited from ifnode framework Component class. This class must be exported by module.exports.

Each component class will be Singleton class and ifnode will create instance of component's class. Initialize options for component will be generated by ifnode or can be set by application configuration.

This instance can be accessed by app.component method (using component class name) in others components or controllers. Also component instance will be attached to app by component class name and can be accessed only by controllers.

Example #

protected/components/MyComponent.js #
const Component = require('ifnode/core/Component');

class MyComponent extends Component {
    constructor() {
        super();
        this._some_internal_value = 'smt';
    }

    do_smt() {
    }
}

module.exports = MyComponent;
app.js #
const IFNode = require('ifnode');
const app = IFNode();

app.load();
app.MyComponent.do_smt();

Injected options #

Application configuration contains special object components with specified settings for target component. Key of configuration components object is a name of component for injecting (name is a component's file name). ifnode automatically injects options from configuration directly to related component. Also options are not required and can be skipped.

Example #
config/local.js #
module.exports = {
    components: {
        Thumbnailer: {
            windowSize: {
                width: 1024,
                height: 768
            }
        }
    }
};
protected/components/Thumbnailer.js #
const Webshot = require('webshot');
const Component = require('ifnode/core/Component');

class Thumbnailer extends Component {
    takeshot(url) {
        return Webshot(url, this.config)
    }
}
app.js #
const IFNode = require('ifnode');
const app = IFNode({
    env: 'local'
});

// load all components and initialize them
app.load();
app.Thumbnailer.takeshot('https://google.com');

Component class instance #

It totally similar to Component class definition but has one maintain difference - creating of component instance will be assigned to developer (component instance must be exported).

Example #

protected/components/MyComponent.js #
const Component = require('ifnode/core/Component');

class MyComponent extends Component {
    do_smt() {
    }
}

module.exports = new MyComponent;
app.js #
const IFNode = require('ifnode');
const app = IFNode();

app.load();
app.MyComponent.do_smt();

Non-Component class #

Using of internal Component class is not required condition for creating components classes. Developer can declare own class without inheriting it and export this class by module.exports. One of most important point is that class will not be instancionate by app.component method invoking and will be returned like defined - just a simple class.

Creating of instance will be assigned to a developer. Instances can be created by new keyword. Also if requires only single instance from class it can be realized by direct exporting instance from component script but I recommended to use Component class/Component class instance definitions types for singleton objects.

Example #

protected/components/MyNonComponent.js #
class MyNonComponent {
    static static_do_smt() {
    }
}

module.exports = MyNonComponent;
protected/components/ComponentFolder/SomeSingletonClass.js #
class SomeSingletonClass {
    do_smt() {
    }
}

module.exports = SomeSingletonClass;
SomeSeparatedComponent.js #
class SomeSeparatedComponent {
    do_smt() {
    }
}

module.exports = SomeSeparatedComponent;
app.js #
const IFNode = require('ifnode');
const app = IFNode();

app.component('MyNonComponent').static_do_smt();
app.component('ComponentFolder/SomeSingletonClass').do_smt();
app.component('./SomeSeparatedComponent') === require('./SomeSeparatedComponent');

Primitive value #

Frequently component can be presented not only by class definition but some function declaration, some constants or all those parts together. Importing of primitive value equal to others definition types by app.component method. It will return a direct exported value from primitive value file.

Example #

protected/components/MyComponent/STATIC_OPTIONS.js #
module.exports = {
    SOME_OPTION: 0
};
protected/components/MyComponent/index.js #
const Component = require('ifnode/core/Component');

class MyComponent extends Component {
    do_smt() {
    }
}

module.exports = MyComponent;
app.js #
const IFNode = require('ifnode');
const app = IFNode();

app.component('MyComponent/STATIC_OPTIONS').SOME_OPTION;
app.component('MyComponent').do_smt();
Table of Content