0.6.1 • Published 5 years ago

fluid-func v0.6.1

Weekly downloads
3
License
MIT
Repository
github
Last release
5 years ago

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)

ParamDescription
errorError instance that contains stack trace and error message
retryFunction that triggers the reprocess of Func
rejectBreaks 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

ParamDescription
currentValueHas 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

ParamDescription
valueHas the current value of the parameter
contextFunc 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

ParamDescription
currentValueHas 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)

ParamDescriptionDefault
cachedForSets the number (in milliseconds) for how long it will cache the Func1500
  
   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

FieldTypeDescriptionRequired
nameStringName of the plugintrue
actionFunctionAction that will runtrue
before/afterarraylist of Func names the action will invoke to before/afteratleast 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

0.6.1

5 years ago

0.6.0

6 years ago

0.5.6

6 years ago

0.5.5

6 years ago

0.5.4

6 years ago

0.5.3

6 years ago

0.5.2

6 years ago

0.5.1

6 years ago

0.5.0

6 years ago

0.4.4

6 years ago

0.4.3

6 years ago

0.4.2

6 years ago

0.4.1

6 years ago

0.4.0

6 years ago

0.3.5

6 years ago

0.3.4

6 years ago

0.3.3

6 years ago

0.3.2

6 years ago

0.3.1

6 years ago

0.3.0

6 years ago

0.2.3

6 years ago

0.2.2

6 years ago

0.2.1

6 years ago

0.2.0

6 years ago

0.1.0

6 years ago