UNPKG

axios-case-converter

Version:

Axios transformer/interceptor that converts snake_case/camelCase

102 lines (90 loc) 3.2 kB
import { camelCase as camelCaseString } from "camel-case"; import { snakeCase as snakeCaseString } from "snake-case"; import { headerCase as headerCaseString } from "header-case"; import { preserveArrayBrackets, preserveSpecificKeys } from "./decorators"; import { isFormData, isTransformable } from "./util"; import { CreateTransform, CreateTransformOf, CreateTransforms, Transformable, Transformer, TransformOptions, TransformUsingCallback, } from "./types"; const transformRecursive = ( data: unknown, fn: Transformer, overwrite: TransformOptions["overwrite"] ): unknown => { if (!isTransformable(data)) { return data; } /* eslint-disable no-console */ if (isFormData(data) && !data.entries) { if (navigator.product === "ReactNative") { console.warn( "Be careful that FormData cannot be transformed on React Native. If you intentionally implemented, ignore this kind of warning: https://facebook.github.io/react-native/docs/debugging.html" ); } else { console.warn( "You must use polyfill of FormData.prototype.entries() on Internet Explorer or Safari: https://github.com/jimmywarting/FormData" ); } return data; } /* eslint-enable no-console */ const prototype = Object.getPrototypeOf(data); const store: Transformable = overwrite ? data : !prototype ? Object.create(null) : new prototype.constructor(); for (const [key, value] of prototype?.entries?.call(data) || Object.entries(data)) { if (prototype?.append) { prototype.append.call( store, typeof key === "string" ? fn(key) : key, transformRecursive(value, fn, overwrite) ); } else if (key !== "__proto__") { store[fn(typeof key === "string" ? key : `${key}`)] = transformRecursive( value, fn, overwrite ); } } return store; }; const transform: TransformUsingCallback = (data, fn, options) => { // Backward compatibility options = typeof options === "boolean" ? { overwrite: options } : options; const composedFn = preserveSpecificKeys( preserveArrayBrackets(fn), options?.preservedKeys || [] ); return transformRecursive(data, composedFn, options?.overwrite || false); }; export const createTransform: CreateTransform = (fn) => { return (data, options): ReturnType<ReturnType<CreateTransform>> => { return transform(data, fn, options); }; }; export const snake = createTransform(snakeCaseString); export const camel = createTransform(camelCaseString); export const header = createTransform(headerCaseString); export const createTransformOf: CreateTransformOf = (functionName, options) => { const fn = options?.[functionName]; return fn ? createTransform(fn) : { snake, camel, header }[functionName]; }; export const createTransforms: CreateTransforms = (options) => { const transforms: ReturnType<CreateTransforms> = { snake, camel, header }; const functionNames = Object.keys(transforms) as (keyof typeof transforms)[]; for (const functionName of functionNames) { transforms[functionName] = createTransformOf(functionName, options); } return transforms; }; export default transform;