Code Monkey home page Code Monkey logo

axios-case-converter's Introduction

axios-case-converter's People

Contributors

amoshydra avatar davidfishlock avatar davidnum avatar joaolrpm avatar mpyw avatar muratozkan avatar siketyan avatar sirajulm avatar stefanbartos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

axios-case-converter's Issues

preservedKeys nested wildcards

Hi,

Nice work you did!
So there's two options to preserve key names, string[] and Function.
I'm currently using the string[] approach, but it might be useful to only apply the middleware only on a subset of the request/response data.

Eg in a Json api there's (very often) extra metadata included in the response:

const requestData = {
  data : {
    data: {
      name: 'name',
      billing_street: 'street name',
      ...
    },
    meta: {
      current_page: 1,
      from: 1, 
      ...
    },
    ...
  }
}

Can we use the Functions-approach here so that the casing middleware is only applied on the data.data attribute?

Thanks!

React Native compatibility

We can never polyfill FormData.prototype.entries() in the current version of React Native (v0.54). We should display warning instead of throwing error.

How to apply middleware only for specific url?

I want to run middleware only for some urls, how can I do it now? I don't really want a separate instance for it, so I'm applying middleware to default object.

Maybe it's a good idea, if you pass your inner functions to caseMiddleware, as a second argument, so we can decide, under which conditions, we'd run it?

    options?.caseMiddleware?.responseTransformer ||
      createCamelResponseTransformer(options),
  ];
  axios.interceptors.request.use(
    options?.caseMiddleware?.requestInterceptor ||
      createSnakeParamsInterceptor(options)
  );

to

    (config) => options?.caseMiddleware?.responseTransformer(config,  createCamelResponseTransformer(options)) ||
      createCamelResponseTransformer(options),
  ];
  axios.interceptors.request.use(
    (config) => options?.caseMiddleware?.requestInterceptor(config, createSnakeParamsInterceptor(options)) ||
      createSnakeParamsInterceptor(options)
  );

but in some more cleaner manner

Not working with JSON.stringify on FormData

Hi, nice to found this awesome library.
I try to use this in my project, but I got the library not covert camelCase to snake_case when sending data with JSON.stringify on FormData.

OS: macOS Mojave
Browser: Google Chrome Version 83.0.4103.116 (Official Build) (64-bit)

And here my code:

// helper: api.js

const API = applyCaseMiddleware(
  Axios.create({
    baseURL: 'http://mysite.com/api/v1/',
    headers: {
      'X-Requested-With': 'xmlhttprequest'
    },
  })
);

export default API;

// main.js

const formData = new FormData();
formData.append('document', null);
formData.append('keterangan', this.form.keterangan);
formData.append('approvers', JSON.stringify(approvers));
API.post('/api/v1/document/store', formData, {
	headers: { 'Content-Type': 'multipart/form-data' }
}).then(res => {
// success
}).catch(err => {
// something went wrong
});

And when checking the browser console, I got this:
Not converted

The data attributes still in camelCase.

How can I fix this?

looks like uuids are behaving weird

Looks like when a uuid is received in a request as a key, funny stuff happens sometimes.

This is what is expected of it:

000_000_aaa_000 => 000-000-aaa-000

However, it sometimes does stuff like:

000_000_aaa_000 => 000-000-aAa-000
000_000_aaa_000 => 000-000aaa000

How to disable headers processing?

The library is perfect.
I would prefer to see headers untouched. Is there any options to disable HTTP headers processing completely, disable it once, and don't worry about keeping preservedKeys up to date.
Thanks.

Axios version dependency warning

When upgrading to axios v0.23.0 on one of my packages I got these npm warnings:

$ npm i [email protected]
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: <my-package>@<my-version>
npm WARN Found: [email protected]
npm WARN node_modules/axios
npm WARN   peer axios@"^0.21.1" from [email protected]
npm WARN   node_modules/axios-case-converter
npm WARN     axios-case-converter@"^0.8.1" from the root project
npm WARN   1 more (the root project)
npm WARN 
npm WARN Could not resolve dependency:
npm WARN peer axios@"^0.21.1" from [email protected]
npm WARN node_modules/axios-case-converter
npm WARN   axios-case-converter@"^0.8.1" from the root project

Maybe it would be better to be less strict in peerDependencies and replace it with something like this:

  "peerDependencies": {
     "axios": ">=0.21.1 <1.0.0"
  }

to avoid these warnings?

Answers for #39 and #40

Answers for #39 and #40

I'm sorry that I'm not willing to implement these features now. I'll explain some reasons. See also the following implementation for reference.

export const applyCaseMiddleware: ApplyCaseMiddleware = (axios, options?) => {
  axios.defaults.transformRequest = [
    options?.caseMiddleware?.requestTransformer ||
      createSnakeRequestTransformer(options),
    ...(Array.isArray(axios.defaults.transformRequest)
      ? axios.defaults.transformRequest
      : axios.defaults.transformRequest !== undefined
      ? [axios.defaults.transformRequest]
      : []),
  ];
  axios.defaults.transformResponse = [
    ...(Array.isArray(axios.defaults.transformResponse)
      ? axios.defaults.transformResponse
      : axios.defaults.transformResponse !== undefined
      ? [axios.defaults.transformResponse]
      : []),
    options?.caseMiddleware?.responseTransformer ||
      createCamelResponseTransformer(options),
  ];
  axios.interceptors.request.use(
    options?.caseMiddleware?.requestInterceptor ||
      createSnakeParamsInterceptor(options)
  );
  return axios;
};

Interceptor

According to the Official Documentation, you can manually apply interceptor like this:

axios.interceptors.request.use(
  options?.caseMiddleware?.requestInterceptor ||
    createSnakeParamsInterceptor(options),
  null,
  { runWhen(config) { /* ... */ } }
);

With this feature, it is possible to implement it on the library side. But I'm not willing to do so because it is difficult to achieve the same functionality on Transformer and it also looks unstable.

Transformer

The implementation in Transformer corresponding to the Interceptor checking runWhen() is the following part.

It looks quite difficult to determine the URL in this layer since request config is not given as an argument here.

Conclusion

The current best practice is:

  • Wrap different Axios instances with your own wrapper function.
  • Decide which Axios instance to use by the the argument condition.

AxiosInstance config doesn't match

Argument of type 'import("xx/node_modules/axios/index").AxiosInstance' is not assignable to parameter of type 'import("xx/node_modules/@types/axios-case-converter/node_modules/axios/index").AxiosInstance'.
  The types of 'defaults.adapter' are incompatible between these types.
    Type 'import("xx/node_modules/axios/index").AxiosAdapter | undefined' is not assignable to type 'import("xx/node_modules/@types/axios-case-converter/node_modules/axios/index").AxiosAdapter | undefined'.
      Type 'import("xx/node_modules/axios/index").AxiosAdapter' is not assignable to type 'import("xx/node_modules/@types/axios-case-converter/node_modules/axios/index").AxiosAdapter'.
        Types of parameters 'config' and 'config' are incompatible.
          Type 'import("xx/node_modules/@types/axios-case-converter/node_modules/axios/index").AxiosRequestConfig' is not assignable to type 'import("xx/node_modules/axios/index").AxiosRequestConfig'.
            Types of property 'method' are incompatible.
              Type 'string | undefined' is not assignable to type '"get" | "GET" | "delete" | "DELETE" | "head" | "HEAD" | "options" | "OPTIONS" | "post" | "POST" | "put" | "PUT" | "patch" | "PATCH" | "link" | "LINK" | "unlink" | "UNLINK" | undefined'.
                Type 'string' is not assignable to type '"get" | "GET" | "delete" | "DELETE" | "head" | "HEAD" | "options" | "OPTIONS" | "post" | "POST" | "put" | "PUT" | "patch" | "PATCH" | "link" | "LINK" | "unlink" | "UNLINK" | undefined'.ts(2345)

Exempt certain fields/nested fields from case conversion

It would be nice to have an options that help you to exempt certain fields from being converted.

For example, we have a field _destroy received from the backend, but after camelCasing it converts to destroy. There is no possibility to send back the field to the API's as _destroy,since _.snakeCase(_destroy) or _.snakeCase(destroy) returns the value as destroy

It will be good if we can have something likethis:

// applyConverters(<axiosInstance>, [<converterOptions>] )
applyConverters(axios.create(), { exception: ['_destroy'] } )

React Native bug with array response

In RN throws iterate exception [object ArrayIterator is not iterable] where response is array of objects like
[{ field: 'foo', message: 'bar' }]

I think this problem around "for...of" operator for array and its polyfill. This bug isnt reproducible for usualy browser enviroment, only for RN. Can you fix it?

Response headers aren't being converted for axios 1.x

Hi! 👋

Firstly, thanks for your work on this project! 🙂

I wanted to bring to your attention an issue I encountered while working on a project that involves updating axios from version 0.24.0 to 1.x and axios-case-converter from version 0.9.0 to 1.1.0.

After the update, I observed a problem related to response headers case conversion. After some debugging, I narrowed down the issue to the overwriteHeadersOrNoop function, particularly the validation within it:

if (
    options?.ignoreHeaders ||
    (!isPlainObject(headers) && !isAxiosHeaders(headers))
)

Upon investigation, it seems that the problem arises when the project is deployed, involving bundling, minification, and obfuscation. The isAxiosHeaders(headers) validation fails, even though the headers are, in fact, of type AxiosHeaders. This occurs because the validation relies on checking the constructor name.

Is there a reason for the use of the constructor name instead of validating whether it is an instance of AxiosHeaders?

To confirm this behavior, I made a patch to the [email protected] and added some log statements to the code:

import { AxiosHeaders } from "axios";

...

const overwriteHeadersOrNoop = (
    ...
): void => {
    console.log(
        `isPlainObject: ${isPlainObject(headers)},
         isAxiosHeaders: ${isAxiosHeaders(headers)},
         instanceof: ${headers instanceof AxiosHeaders}
    `);
}

When running the code locally, the logs showed the expected results. However, after deployment, the logs indicated that isAxiosHeaders(headers) was returning false, even though headers instanceof AxiosHeaders was true.

Local Logs:
local

Deployed Logs:
docker-compose

It appears that the issue might be related to the obfuscation process affecting the constructor name comparison.

For additional context, here is the configuration for the Axios instance and the relevant request:

Axios Instance:

const axiosInstance = applyConverters(
  axios.create({
    baseURL: SOME_URL,
    timeout: 10000,
    paramsSerializer: (params) => stringify(params, { arrayFormat: 'repeat' }),
  })
);

Request:

axiosInstance.post(SOME_URL, formData, {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
});

On Success:

const something = data.headers.contentLocation;  // Fails due to incorrect case conversion

If you need any more details or if there's anything else I can do to assist in the resolution process, please let me know.

Thank you for your time and attention to this matter.

preserve case

I switched from camelize to this project because this allowed configuration.

I know issues are not for how tos but maybe you have a quick answer...

How to not change case? BMX is being converted into bmx

Add option to preserve uuids

I was recently hunting down a bug in an application where object keys appeared to be missing (although I could see them in the API response) only to later find out that they were (of course) converted to "camelcase". So
445ebf68-bd0e-44c6-b6b8-a70d9ba08115 became 445ebf68Bd0e44c6B6b8A70d9ba08115.

Would be nice to have an option like { preserveUuid: true } to not convert UUIDs (or possibly other formats) to camelCase. If you're interested, I could build that and create a PR.

Another, more flexible option would be something like a preservePattern: RegExp so a user could specify which keys should not be converted but I think preserveUuid would be fine for the beginning 😉

Ping me if you're interested!

TypeError: applyCaseMiddleware is not a function

Getting TypeError: applyCaseMiddleware is not a function when using in Node 16.x with type module enabled.

import axios from 'axios';
import applyCaseMiddleware from 'axios-case-converter';

const axiosInstance = applyCaseMiddleware(axios.create());

How to disable some of the transformations?

Hello,

The readme is unclear to me :

  • I want the data's keys to be camelCase,
    BUT
  • I don't want any of the other transformations: no changing the headers (for that there's ignoreHeaders, I believe?), no changing query parameters to snake case

How do I configure that in the options?

camel case converter is not following the default rules.

main code:

    camel: (input, options) => {
      return (input.charAt(0).toLowerCase() + input.slice(1)).replace(/[-_](.)/g, (match, group1) => group1.toUpperCase());
    }

=>

input : pub_pub_256 
return: pubPub256

however, when deployed with axios, it will return pubPub_256, instead of pubPub256.

Current work around is prepadding a char before numeric.

opt-out for transforming params casing

Hi,

I am wondering whether is possible to add an opt-out flag to not transform query params at all. It could be done in the same manner as ignoreHeaders.

Thx

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.