<commit_before>/* @flow */
type QueryParams = {[key: string]: any};

/**
 * This will get a queryParam from the passed url string
 * @param  queryParamKey  The key for the queryParam
 * @param  defaultValue   The default value to return when nothing is available
 * @return                The value of the queryParam
 */
export const getQueryParam = (queryParamKey: string, defaultValue: ?string): ?string => {
  const queryParam = context.getVariable('request.queryparam.' + queryParamKey);

  return queryParam === undefined || queryParam === null ? defaultValue : queryParam;
};

/**
 * This will get a set of queryParams from the passed url string
 * @param  possibleQueryParams    An array containing possible queryparams
 * @param  settings               Object containing the settings for getting the queryparams
 * @param  settings.defaultValues The value to return when no value is found. The keys of the default values should be identical to the queryparam keys.
 * @return                        An object containing values for the passed in queryparams
 */
// $FlowBug: Flow doesn't support default function parameter in combination with destructering
export const getQueryParams = (possibleQueryParams: Array<string>, {
  defaultValues = {},
} = {
  defaultValues: {},
}) => possibleQueryParams.reduce((queryParams: QueryParams, possibleQueryKey: string): QueryParams => ({
    ...queryParams,
    [possibleQueryKey]: getQueryParam(possibleQueryKey, defaultValues[possibleQueryKey]),
  }), defaultValues);
// defaultValues: {[key: string]: string}

/**
 * This will convert an object with key value pairs to a new object with key value pairs
 * @param  queryParams            An object containing key value pairs to be used as query parameters
 * @param  settings               Object containing the settings for creating the queryparams
 * @param  settings.renamer       The name of the keys to rename. In a format of oldname: newname
 * @param  settings.defaultValues The value to return when no value is found. The keys of the default values should be identical to the queryparam keys.
 * @param  settings.transformer   A transformer object contains functions which take a value and return a new value. The keys of the transformer should be identical to the queryparam keys.
 */
// $FlowBug: Flow doesn't support default function parameter in combination with destructering
export const createQueryParams = (queryParams: {[key: string]: any}, {
  renamer = {},
  defaultValues = {},
  transformer = {},
} = {
  renamer: {},
  defaultValues: {},
  transformer: {},
}) => Object.keys(queryParams).reduce((nextQueryParams, key) => ({
  ...nextQueryParams,
  [renamer[key] || key]: queryParams[key] !== undefined && queryParams[key] !== null ?
    transformer[key] ?
      transformer[key](queryParams[key]) :
      queryParams[key] :
    defaultValues[key],
}), defaultValues);
//   renamer: {[key: string]: string},
//   defaultValues: {[key: string]: string},
//   transformer: {[key: string]: any},

/**
 * This will set a query parameter to the provided value
 * @param  key   The key of the queryparam to set
 * @param  value The value to set the queryparam to
 */
export const setQueryParam = (key: string, value: any): void => context.setVariable(`request.queryparam.${key}`, value);

/**
 * This will convert an object with key value pairs to query parameters
 * @param  queryParams   An object containing key value pairs to be used as query parameters
 */
export const setQueryParams = (queryParams: {[key: string]: any}): void =>
  Object.keys(queryParams).forEach((key: string): void => setQueryParam(key, queryParams[key]));

/**
 * This will validate a set of query parameters and will set a error variable in the apigee with an errorpayload variable which can be send down to the client
 * It is advised to set up a raise on error policy which will return the payload when the error variable == true
 * @param  queryParams          The keys the values to get are stored with
 * @param  settings             Object containing the settings for getting the variables
 * @param  settings.validator   The validator is an object containing functions which take a value and tests whether the value matches to required format returning true for a valid parameter and false for invalid. Or it can return a custom error message as a string. It is also possible to return mutliple error messages as an array of strings. The keys of the validator should be identical to the queryparam keys.
 * @return                      A boolean indicating whether an invalid query param was detected or not
 */
// $FlowBug: Flow doesn't support default function parameter in combination with destructering
export const validateQueryParams = (queryParams: QueryParams, {
  validator = {},
} = {
  validator: {},
}) => {
  const error = {
    error: false,
    payload: {
      errors: [],
    },
  };

  Object.keys(queryParams).forEach((key: string): void => {
		if (queryParams[key] !== undefined && queryParams[key] !== null && validator[key]) {
      const validatorResponse: boolean | string | Array<string> = validator[key](queryParams[key]);
      const invalidResponse: boolean = validatorResponse === false ||
        typeof validatorResponse === 'string' && validatorResponse !== '' ||
        Array.isArray(validatorResponse) && !validatorResponse.length;

      if (invalidResponse) {
        const errorMessage: string | Array<string> = typeof validatorResponse === 'boolean' ? '' : validatorResponse;

        error.payload.errors = !Array.isArray(errorMessage) ?
          [...error.payload.errors, createErrorObject(key, queryParams[key], errorMessage)] :
          [...error.payload.errors, ...errorMessage.map((singleErrorMessage: string) => createErrorObject(key, queryParams[key], singleErrorMessage))];
      }
    }
	});

  if (error.payload.errors.length) {
    error.payload = {
      title: 'Invalid query parameter',
      message: 'One or more query parameters are invalid',
      statusCode: 400,
      errors: error.payload.errors,
    };
  }

  setVariables({
    error: error.error,
    errorpayload: JSON.stringify(error.payload),
  }, {
    prefix: '',
  });

  return error.error;
};
// validator?: {[key: string]: (value: string) => boolean | string | Array<string>},

<commit_msg>Added prefix for the queryparam validation<commit_after>/* @flow */
type QueryParams = {[key: string]: any};

/**
 * This will get a queryParam from the passed url string
 * @param  queryParamKey  The key for the queryParam
 * @param  defaultValue   The default value to return when nothing is available
 * @return                The value of the queryParam
 */
export const getQueryParam = (queryParamKey: string, defaultValue: ?string): ?string => {
  const queryParam = context.getVariable('request.queryparam.' + queryParamKey);

  return queryParam === undefined || queryParam === null ? defaultValue : queryParam;
};

/**
 * This will get a set of queryParams from the passed url string
 * @param  possibleQueryParams    An array containing possible queryparams
 * @param  settings               Object containing the settings for getting the queryparams
 * @param  settings.defaultValues The value to return when no value is found. The keys of the default values should be identical to the queryparam keys.
 * @return                        An object containing values for the passed in queryparams
 */
// $FlowBug: Flow doesn't support default function parameter in combination with destructering
export const getQueryParams = (possibleQueryParams: Array<string>, {
  defaultValues = {},
} = {
  defaultValues: {},
}) => possibleQueryParams.reduce((queryParams: QueryParams, possibleQueryKey: string): QueryParams => ({
    ...queryParams,
    [possibleQueryKey]: getQueryParam(possibleQueryKey, defaultValues[possibleQueryKey]),
  }), defaultValues);
// defaultValues: {[key: string]: string}

/**
 * This will convert an object with key value pairs to a new object with key value pairs
 * @param  queryParams            An object containing key value pairs to be used as query parameters
 * @param  settings               Object containing the settings for creating the queryparams
 * @param  settings.renamer       The name of the keys to rename. In a format of oldname: newname
 * @param  settings.defaultValues The value to return when no value is found. The keys of the default values should be identical to the queryparam keys.
 * @param  settings.transformer   A transformer object contains functions which take a value and return a new value. The keys of the transformer should be identical to the queryparam keys.
 */
// $FlowBug: Flow doesn't support default function parameter in combination with destructering
export const createQueryParams = (queryParams: {[key: string]: any}, {
  renamer = {},
  defaultValues = {},
  transformer = {},
} = {
  renamer: {},
  defaultValues: {},
  transformer: {},
}) => Object.keys(queryParams).reduce((nextQueryParams, key) => ({
  ...nextQueryParams,
  [renamer[key] || key]: queryParams[key] !== undefined && queryParams[key] !== null ?
    transformer[key] ?
      transformer[key](queryParams[key]) :
      queryParams[key] :
    defaultValues[key],
}), defaultValues);
//   renamer: {[key: string]: string},
//   defaultValues: {[key: string]: string},
//   transformer: {[key: string]: any},

/**
 * This will set a query parameter to the provided value
 * @param  key   The key of the queryparam to set
 * @param  value The value to set the queryparam to
 */
export const setQueryParam = (key: string, value: any): void => context.setVariable(`request.queryparam.${key}`, value);

/**
 * This will convert an object with key value pairs to query parameters
 * @param  queryParams   An object containing key value pairs to be used as query parameters
 */
export const setQueryParams = (queryParams: {[key: string]: any}): void =>
  Object.keys(queryParams).forEach((key: string): void => setQueryParam(key, queryParams[key]));

/**
 * This will validate a set of query parameters and will set a error variable in the apigee with an errorpayload variable which can be send down to the client
 * It is advised to set up a raise on error policy which will return the payload when the error variable == true
 * @param  queryParams          The keys the values to get are stored with
 * @param  settings             Object containing the settings for getting the variables
 * @param  settings.validator   The validator is an object containing functions which take a value and tests whether the value matches to required format returning true for a valid parameter and false for invalid. Or it can return a custom error message as a string. It is also possible to return mutliple error messages as an array of strings. The keys of the validator should be identical to the queryparam keys.
 * @return                      A boolean indicating whether an invalid query param was detected or not
 */
// $FlowBug: Flow doesn't support default function parameter in combination with destructering
export const validateQueryParams = (queryParams: QueryParams, {
  validator = {},
  prefix = '',
} = {
  validator: {},
  prefix: '',
}) => {
  const error = {
    error: false,
    payload: {
      errors: [],
    },
  };

  Object.keys(queryParams).forEach((key: string): void => {
		if (queryParams[key] !== undefined && queryParams[key] !== null && validator[key]) {
      const validatorResponse: boolean | string | Array<string> = validator[key](queryParams[key]);
      const invalidResponse: boolean = validatorResponse === false ||
        typeof validatorResponse === 'string' && validatorResponse !== '' ||
        Array.isArray(validatorResponse) && !validatorResponse.length;

      if (invalidResponse) {
        const errorMessage: string | Array<string> = typeof validatorResponse === 'boolean' ? '' : validatorResponse;

        error.payload.errors = !Array.isArray(errorMessage) ?
          [...error.payload.errors, createErrorObject(key, queryParams[key], errorMessage)] :
          [...error.payload.errors, ...errorMessage.map((singleErrorMessage: string) => createErrorObject(key, queryParams[key], singleErrorMessage))];
      }
    }
	});

  if (error.payload.errors.length) {
    error.payload = {
      title: 'Invalid query parameter',
      message: 'One or more query parameters are invalid',
      statusCode: 400,
      errors: error.payload.errors,
    };
  }

  setVariables({
    error: error.error,
    errorpayload: JSON.stringify(error.payload),
  }, {
    prefix,
  });

  return error.error;
};
// validator?: {[key: string]: (value: string) => boolean | string | Array<string>},


{'fraction_non_alphanumeric': 0.1033096926713948, 'fraction_numerical': 0.00047281323877068556, 'mean_word_length': 3.7038547071905117, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1823974', 'n_tokens_mistral': 3218, 'n_tokens_neox': 3184, 'n_words': 1307}