fluid-func

0.6.1 • Public • Published

fluid-func

A way to write your code with functional programming in mind

NPM Download Stats

Getting started

  • Installation
    npm install --save fluid-func
  • Javascript (ES6)
    import FluidFunc from 'fluid-func';
  • Javascsript
   var FluidFunc = require('fluid-func');

Note: This package is basically a fork of fluid-chains with lighter packaging, less dependencies, a more secure aproach to chaining functions and focused on functional programming.

Two ways to create a Func

    new FluidFunc('_1stFunc', function(parameter){
        // do some work here
    });
    FluidFunc.create('_1stFunc')
        .onStart(function(paramater){
            //do some work here
        });

Two ways to start a Func

    FluidFunc.start('_1stFunc', {paramName:'paramVAlue'})
        .then(function(result){
            // do some work after
        })
        .catch(function(err){
            // do some error handling
        });
    FluidFunc.create('_1stFunc')
        .onStart(function(paramater){
            //do some work here
        }).execute({paramName:'paramVAlue'})
        .then(function(result){
            // do some work after
        })
        .catch(function(err){
            // do some error handling
        });

Creating a Func sequence

 
    new FluidFunc('_1stFunc', function(param){
        // do the first func
    });
 
    new FluidFunc('_2ndFunc',function(param){
        //do the 2nd func
    });
 
    FluidFunc.start(['_1stFunc','_2ndFunc'], {paramName:'paramValue'})
        .then(function(result){
            // do something after
        })
        .catch(function(err){
            // do some error handling
        });
 
    FluidFunc.create('_1stFunc')
        .onStart(function(param){
            // do the first func
        })
        .connect('_2ndFunc')
        .onStart(function(param){
            // do the 2nd func
        })
        .execute({paramName:'paramValue'})
        .then(function(result){
            // do something after
        })
        .catch(function(err){
            // do some error handling
        });

Accessing a parameter

Parameters are immutable and can be accessed by calling the field as function.

    new FluidFunc('_1stFunc', function(param){
        // do the first func
        const paramValue = param.paramName();
    });
 
    FluidFunc.start('_1stFunc'], {paramName:'paramValue'})
        .then(function(result){
            // do something after
        })
        .catch(function(err){
            // do some error handling
        });
 

Maintaining a context

The first parameter is accessible across the Func sequence.

    new FluidFunc('_1stFunc', function(param){
        // do the first func
        const paramValue = param.paramName();
    });
 
    new FluidFunc('_2ndFunc',function(param){
        //do the 2nd func
         const paramValue = param.paramName();
    });
 
    FluidFunc.start(['_1stFunc','_2ndFunc'], {paramName:'paramValue'})
        .then(function(result){
            // do something after
        })
        .catch(function(err){
            // do some error handling
        });

In Func sequence you can set the next parameter by returning a value or an object in the action method.

    new FluidFunc('_1stFunc', function(param){
        // do the first func
        const paramValue = param.paramName();
        return {
            from1st:'_1st says hi',
            person: {
                name: 'John Doe',
                age: 22
            }
        };
    });
 
    new FluidFunc('_2ndFunc',function(param){
        //do the 2nd func
         const paramValue = param.paramName();
         const _1stSaysHi = param.from1st(); // got from the previous func
         const name = param.person('name');
    });
 
    FluidFunc.start(['_1stFunc','_2ndFunc'], {paramName:'paramValue'})
        .then(function(result){
            // do something after
        })
        .catch(function(err){
            // do some error handling
        });

Returning a literal value will be accessible by paramater.value on the next Func.

    new FluidFunc('_1stFunc', function(param){
        // do the first func
        const paramValue = param.paramName();
        return '_1st says hi';
    });
 
    new FluidFunc('_2ndFunc',function(param){
        //do the 2nd func
         const paramValue = param.paramName();
         const _1stSaysHi = param.value(); // got from the previous func
    });
 
    FluidFunc.start(['_1stFunc','_2ndFunc'], {paramName:'paramValue'})
        .then(function(result){
            // do something after
        })
        .catch(function(err){
            // do some error handling
        });

Returning a promise in Func

    new FluidFunc('_1stFunc', function(param){
        // do the first func
        const paramValue = param.paramName();
        return new Promise(function(resolve,reject){
            resolve('_1st says hi');
        });
    });
 
    new FluidFunc('_2ndFunc',function(param){
        //do the 2nd func
         const paramValue = param.paramName();
         const _1stSaysHi = param.value(); // got from the previous func
    });
 
    FluidFunc.start(['_1stFunc','_2ndFunc'], {paramName:'paramValue'})
        .then(function(result){
            // do something after
        })
        .catch(function(err){
            // do some error handling
        });

Restricting parameters with func.strict

If you want to be strict with parameters and get only what you need you can enable strict mode per func.

 
    new FluidFunc('_2ndFunc', function(parameters){
        const paramValue = parameters.paramName();
        const iNeedThisAlso = parameters.moreParam();
        // parameters.fillerParam will be undefined
    })
    .strict()
    .spec('paramName')
    .spec('moreParam');
 
    FluidFunc.start('_1stFunc',
     {paramName:'paramValue',
     fillerParam:'not needed value',
     moreParam:'I need this also'})
        .then(function(result){
            // do something after
        })
        .catch(function(err){
            // do some error handling
        });

func.onBefore

If you want to have something to do before runing the Func use the func.onBefore.

 
    new FluidFunc('_1stFunc', function(parameter) {
 
    })
    .onBefore(function(paramater){
        /* do some security check here or something you do before running the func */
 
        return true; // Func will continue to start
    });

Using promises.

 
    new FluidFunc('_1stFunc', function(parameter) {
        // do some func thingy here
    })
    .onBefore(function(paramater){
        /* do some security check here or something you do before running the func */
 
        return new Promise(funciton(resolve, reject){
            resolve(true);// Func will continue to start
        });
    });

Note: FluidFunc will just skip and continue to the next Func when you return false value.

func.onFail

A way to handle error or breakage in Func process. In this you have options to retry the Func or break the sequence.

 
    new FluidFunc('_1stFunc', function(parameter) {
        // do some func thingy here
    })
    .onFail(function(error, retry, reject){
        retry();// will re process the Func
    });

onFail: Function(error: Error, retry: Function, reject: Function)

Param Description
error Error instance that contains stack trace and error message
retry Function that triggers the reprocess of Func
reject Breaks the Func sequence

Specifications and validations with func.spec

spec.require

  • To require value from parameters add require:true in spec
 
    new FluidFunc('_1stFunc', function(parameter){
        const mandatoryField = parameter.mandatoryField(); //this field will always have value
    })
    .spec('mandatoryField', {
        require:true
    });
 
    FluidFunc.start('_1stFunc', {
        mandatoryField: 'hello'
    });
 
  • Adding custom message
 
    new FluidFunc('_1stFunc', function(parameter){
        const mandatoryField = parameter.mandatoryField(); //this field will always have value
    })
    .spec('mandatoryField', {
        require:true,
        requireMessage:'mandatory field is needed.'
    });
 
    FluidFunc.start('_1stFunc', {
        mandatoryField: 'hello'
    });
 
  • Transforming the parameter value

transform: Function(current: String): Promise

Param Description
currentValue Has the current value of the parameter

Note: Transform function should always return Promise

 
    new FluidFunc('_1stFunc', function(parameter){
        const userData = parameter.user(); // this is now a user object
    })
    .spec('user', {
        require:true,
        requireMessage:'UserId field is needed.'
    }, transform: function(currentValue){
        return new Promise((resolve,reject)=>{
            FindUserById(currentValue)
                .then(function(user){
                    resolve(user);
                })
                .catch(function(err){
                    reject(err);
                });
        });
    });
 
    FluidFunc.start('_1stFunc', {
        user: '#432userID'
    });
 
  • Translating the parameters

Tranlates the parameter value into a new sets of parameters

transform: Function(current: String): Promise

Param Description
value Has the current value of the parameter
context Func current context

Note: Tranlate function should always return Promise

 
    new FluidFunc('_1stFunc', function(parameter){
        const username = parameter.username();
        const fullname = parameter.fullname();
    })
    .spec('user', {
        require:true,
        requireMessage:'User field is needed.'
    }, translate: function(currentValue, context){
        return new Promise((resolve, reject)=>{
            context.set('username', currentValue.username);
            context.set('fullname', currentValue.fullname);
            resolve();
        });
    });
 
    FluidFunc.start('_1stFunc', {
        user: {
            username: 'rickzx98',
            fullname: 'Jerico de Guzman'
        }
    });
 
  • Customer validator

validate: Function(current: String): Promise

Param Description
currentValue Has the current value of the parameter
    new FluidFunc('_1stFunc', function(parameter){
        const userData = parameter.user(); // this is now a user object
    })
    .spec('user', 
     validate: function(currentValue){
        return new Promise((resolve,reject)=>{
            if(currentValue === validEmail){
                resolve();
            } else{
                reject();
            }
        });
    });
 
    FluidFunc.start('_1stFunc', {
        email: 'john.doe@email.com'
    });

Reducer

To make the Func act as reducer use func.reduce(${fieldToReduce})

 
        new FluidFunc('_1stFunc', (parameter, current, index) => {
            return current + (parameter.value ? parameter.value() : 0);
        }).reduce('sampleArray');
 
        FluidFunc.start('_1stFunc', { sampleArray: [1, 2, 3, 4, 5] })
            .then(result => {
                //expect(result.value()).to.be.equal(15);
            });

Cache

func.cache(cachedFor:number)

Param Description Default
cachedFor Sets the number (in milliseconds) for how long it will cache the Func 1500
  
   var counter = 0;
 
   new FluidFunc('_1stFunc', (parameter) => {
        counter++;
            return '_1st';
        })
        .strict()
        .cache();
 
   new FluidFunc('_2ndFunc', (parameter) => {
        counter++;
            return '_2nd';
        })
        .strict()
        .cache();
 
FluidFunc.start(['_1stFunc','_2ndFunc','_1stFunc','_2ndFunc'], {
    hi:'hello'})
    .then(()=>{
        //counter will be equal to two
    });
 

Note: The cache is based on the parameter set to the Func action so enabling .strict() mode will make cache more effective.

Monitoring

To monitor a single Func action you must do the following:

    FluidFunc.config({
        logMonitor: function(monitor) {
              //console.log(monitor);
        }
    });
  • Monitor contains the detail of every Func process including it parameters and resolved context.

Plugins

Field Type Description Required
name String Name of the plugin true
action Function Action that will run true
before/after array list of Func names the action will invoke to before/after atleast one of either
  • Plugin.action: Function(context: Context) - Will handle the plugin execution. All return types will be merged to the Context parameter.
  • Plugin.before - Will run the plugin before executing the Func
  • Plugin.after - Will run the plugin after the Func completes
    FluidFunc.config({
        plugins: [
            {
            name:'AwesomePlugin', 
            action: function(context) {
                return "hello";
            },
            before:['Func1'],
            after:['Func2']
            }
        ]
    });
 
    FluidFunc.create('Func1').onStart(function(parameter){
        parameter.AwesomePlugin() // hello
    });
 
    FluidFunc.create('Func2').onStart(function(){})
    .execute(result => { 
        // plugin was triggered after Func2
        result.AwesomePlugin() // hello
    });
 

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License - see the LICENSE.md file for details

Package Sidebar

Install

npm i fluid-func

Weekly Downloads

0

Version

0.6.1

License

MIT

Unpacked Size

114 kB

Total Files

47

Last publish

Collaborators

  • rickzx98