All files / src/utils camelify.ts

100% Statements 19/19
100% Branches 8/8
100% Functions 7/7
100% Lines 15/15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41  1x 1x 50x 39x 1x 1x 7x     1x 3x 3x 3x 20x   11x 3x   1x                                          
import { camelCase, fromPairs, negate, toPairs } from "lodash";
 
export type PredicateFn = (a: any) => boolean;
export type MapFn<A = any, B = any> = (x: A) => B;
export type KeyMapFn = MapFn<string, string>;
 
export interface CamelifyOptions {
  exclude: PredicateFn;
  keyMapper: KeyMapFn;
}
 
export const when = (p: PredicateFn, f: MapFn) => (x: any) => (p(x) ? f(x) : x);
 
const isMappable = (x: any) => x != null && typeof x === "object" && !(x instanceof Date);
 
const defaultOptions = {};
const defaultConfig: CamelifyOptions = {
  exclude: (k: string) => k.startsWith("_"),
  keyMapper: camelCase,
};
 
export const camelCaseifier = (options: Partial<CamelifyOptions> = defaultOptions) => {
  const config = { ...defaultConfig, ...options };
  const { exclude, keyMapper } = config;
  const mapKey = when(negate(exclude), keyMapper);
 
  const transformFn = when(
    isMappable,
    x =>
      Array.isArray(x)
        ? x.map(transformFn)
        : {
            ...fromPairs(toPairs(x).map(([k, v]) => [mapKey(k), transformFn(v)])),
          },
  );
 
  return transformFn;
};
 
export default camelCaseifier();