Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function Wrapper for 8base functions #21

Closed
kikeztw opened this issue Jul 4, 2021 · 3 comments
Closed

Function Wrapper for 8base functions #21

kikeztw opened this issue Jul 4, 2021 · 3 comments
Assignees
Labels
enhancement New feature or request

Comments

@kikeztw
Copy link

kikeztw commented Jul 4, 2021

Description

Function Wrapper for 8 base functions. This function separates the logic of obtaining the variables of enteronos or the feature flags from the logic of the function. The environment variables and the feature flags are standardized so we could add that logic in the wrapper

Note: This would be a quick example, it would not be the final wrapper, you would have to make some changes

import { FunctionContext, FunctionResult, FunctionEvent } from '8base-cli-types';

type Options= {
  env?: string[];
};

type CallBackValues<T> = {
  event: FunctionEvent<T>;
  context: FunctionContext;
  env: object;
};

type CallBackType <T = unknown> = (options: CallBackValues<T>) => Promise<FunctionResult>;
type FunctionWrapperReturnType <T = unknown> = (cb: CallBackType<T>) => EichBaseFunction<T>;
type EichBaseFunction <T = unknown> = (event: FunctionEvent<T>, context: FunctionContext) => Promise<FunctionResult>;

export function functionsWrapper<T> (options?: Options): FunctionWrapperReturnType<T> {
  return (cb: CallBackType<T>) => {
    return async (event, context): Promise<FunctionResult> => {
      // dot something here
      if(options.env){
        const env = await getEnv(options.env, context);
      }
      
      if(options.getCurrentUser){
        const currentUser = await getCurrentUser(context);
      }
      
      if(options.checkFunctionFlag){
        const isDisabled = await getFeatureFlag(options.checkFcuntionFlag, context);
      }

      try{
        return cb({ event, context, env, isDisabled, currentUser });
      }catch(error){
        throw new Error(error)
      }
    }
  }
}

Example in function

// from the function file.
import { functionsWrapper } from 'package-name';


const options = { 
  env: ['POST_BACK', 'API_URL'],
  getCurrentUser: true,
  checkFunctionFlag: ['EDIT_CLIENT_TASK']
}

type EventTest = {
  id: string;
}


export default functionsWrapper<EventTest>(options)(
  async ({ event, context, env, currentUser }): Promise<FunctionResult> => {
  const { id } = event?.data;
  
  if(currentUser.id !== id){
    throw new Error('this user cant edit the client');
  }

  console.log(env.POST_BACK, env.API_URL);

  const request = await context.api.gqlRequest(QUERY, { id  });

  return {
    errors: []
  }
})
@kikeztw kikeztw added the enhancement New feature or request label Jul 4, 2021
@jesusrodrz
Copy link

@alacret what you think?

@alacret
Copy link
Contributor

alacret commented Jul 7, 2021

I like the concept as is being tried to achieve, my comments:

  • I think a good and clean way to do this is using decorators, or "wrappers", but I think that the Javascript community is not very supportive to function wrappers or decorators, rather the preference is currying or other forms of composition.

Other languages support:

@FeatureFlag('SEND_EMAIL')
function(param1, param2, context) {
     const ffSendEmail = context[0];
    ...
}

But this in javascript can lead to undesired behavior due to hoisting variables:
https://stackoverflow.com/questions/31771856/decorators-on-functions
https://esdiscuss.org/topic/decorators-for-functions
wycats/javascript-decorators#4

  • I think that we can solve this using DI or simply a singleton class with static methods:

Example

module.exports = async (event, context) => {
    const featureFlag = Util8base.resolveFeatureFlag('SEND_EMAIL', cache: 0);
    const [featureFlag,featureFlag2 ] = Util8base.resolveFeatureFlag(['SEND_EMAIL', 'SALESFORCE_INTEGRATION']);
    const templateId = Util8base.resolveSystemSetting('SENDGRID_TEMPLATE', cache:90)
    
    //  For the current User
    const user = Util8base.resolveUser();

    // For Graphql queries, is important to allow multiple for efficiency
    const [result1, result2] = Util8base.resolveQuery([FETCH_ROLES_QUERY, FETCH_COMPANY], cache:60);
}

@kikeztw
Copy link
Author

kikeztw commented Jul 12, 2021

Example

module.exports = async (event, context) => {
    const featureFlag = Util8base.resolveFeatureFlag('SEND_EMAIL', cache: 0);
    const [featureFlag,featureFlag2 ] = Util8base.resolveFeatureFlag(['SEND_EMAIL', 'SALESFORCE_INTEGRATION']);
    const templateId = Util8base.resolveSystemSetting('SENDGRID_TEMPLATE', cache:90)
    
    //  For the current User
    const user = Util8base.resolveUser();

    // For Graphql queries, is important to allow multiple for efficiency
    const [result1, result2] = Util8base.resolveQuery([FETCH_ROLES_QUERY, FETCH_COMPANY], cache:60);
}

The principle of the wrapper was to separate the logic of accessing the fatureFlag or the environment variables of the function and only pass the results through parameters. But I will review this alternative

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants