Search code examples
javascriptnode.jsecmascript-6composition

Dynamically wrap named exports with extra middleware before exporting


I have a few exported functions from ES6 module like:

export const funA = params => 'hello funA';
export const funB = params => 'hello funB';

I'd like to wrap them before exporting:

const wrapper = params => fun => {
  // some extra logic
  Object.assign(params, { extra: 'data' });
  return fun(params);
};

export const funA = wrapper(params => 'hello funA');
export const funB = wrapper(params => 'hello funB');

It works this way, but I'm wondering if it's possible to define funA and funB without wrapper invocation in a way simmilar to:

import { mapValues } from 'lodash';

const wrapper = params => fun => {
  // some extra logic
  Object.assign(params, { extra: 'data' });
  return fun(params);
};

const funA = params => 'hello funA';
const funB = params => 'hello funB';

export default mapValues({ funA, funB }, wrapper);

The issue with above snippet is that named exports are not used.

Can I achieve named exports with possibility to wrap them with wrapper middleware dynamically?


Solution

  • Where are you going to determine which wrapper middleware?

    You could do something like

    export const funA = middleware => params => 'funA'
    export const funB = middleware => params => 'funB'
    

    then at the callsite:

    import { funA } from './module.js'
    
    const funFunA = middleware(funA)
    

    But this is sounding more and more like a case for function composition:

    import { funA } from './module.js'
    import { nextFun } from './other.js'
    
    const funFunA = compose(nextFun, funA)
    

    Depending on your needs it might also be worth your while using something like the Arrow monad

    https://evilsoft.github.io/crocks/docs/crocks/Arrow.html

    Edit:

    const _funA = a => b
    
    export const funA = (...args) => {
      switch (currentMood) {
        case 'saucy': return sauce(_funA(...args))
        default: return _funA(...args)
    }