-
-
Notifications
You must be signed in to change notification settings - Fork 533
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
Fixes #1252. Adds --transformCase flag. #1465
base: main
Are you sure you want to change the base?
Conversation
This is super helpful! One note - since the library handles the API requests, I would expect it to also handle original case -> chosen case conversion for the response body. Perhaps there could be an option
I didn't find an obvious way to hook up a middleware into the generated services. 😕 Maybe someone can share their approach. |
@petrgazarov oh sorry for not being more specific. We don't use the generated services from this tool (at least not yet). We have a custom fetch function that we've written that handles our authentication and converting the keys. I have a break coming up next week and one of the things I wanted to do was look into the services code to see if it would make sense to have a way to convert the bodies. If you're able to share an example of the behavior you want, I could look into how to do it. |
Hey @robdodson, I'm using a custom request file to convert the body keys between snake and camel cases. It works fine in tandem with the Here is my import axios from 'axios';
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
import FormData from 'form-data';
-import { ApiError } from './ApiError';
-import type { ApiRequestOptions } from './ApiRequestOptions';
-import type { ApiResult } from './ApiResult';
-import { CancelablePromise } from './CancelablePromise';
-import type { OnCancel } from './CancelablePromise';
-import type { OpenAPIConfig } from './OpenAPI';
+import { ApiError } from '@/api/client/core/ApiError';
+import type { ApiRequestOptions } from '@/api/client/core/ApiRequestOptions';
+import type { ApiResult } from '@/api/client/core/ApiResult';
+import { CancelablePromise } from '@/api/client/core/CancelablePromise';
+import type { OnCancel } from '@/api/client/core/CancelablePromise';
+import type { OpenAPIConfig } from '@/api/client/core/OpenAPI';
+
+// ------------ function to camelize keys ----------------
+import { isArray, isObject, camelCase, transform } from 'lodash';
+const camelizeKeys = (obj: any) =>
+ transform(obj, (acc: { [key: string]: any }, value, key: string, target) => {
+ const camelKey = isArray(target) ? key : camelCase(key);
+
+ acc[camelKey] = isObject(value) ? camelizeKeys(value) : value;
+ });
+// ---------------------------------------------------------------
+
+// ------------ function to convert keys to snake case ----------------
+import { snakeCase } from 'lodash';
+const convertKeysToSnakeCase = (obj: any) =>
+ transform(obj, (acc: { [key: string]: any }, value, key: string, target) => {
+ const snakeCaseKey = isArray(target) ? key : snakeCase(key);
+
+ acc[snakeCaseKey] = isObject(value) ? convertKeysToSnakeCase(value) : value;
+ });
+// ---------------------------------------------------------------
@@ -207,7 +238,7 @@ const sendRequest = async <T>(
const requestConfig: AxiosRequestConfig = {
url,
headers,
- data: body ?? formData,
+ data: body ? convertKeysToSnakeCase(body) : formData,
method: options.method,
withCredentials: config.WITH_CREDENTIALS,
cancelToken: source.token,
@@ -216,7 +247,10 @@ const sendRequest = async <T>(
onCancel(() => source.cancel('The user aborted a request.'));
try {
- return await axios.request(requestConfig);
+ return await axios.request(requestConfig).then((response) => {
+ response.data = camelizeKeys(response.data);
+ return response;
+ });
} catch (error) {
const axiosError = error as AxiosError<T>;
if (axiosError.response) {
@@ -226,7 +260,10 @@ const sendRequest = async <T>(
}
}; |
I tested this locally and it had some minor issues. It does not convert the case of linked/nested fields. I fixed it in this PR. @robdodson please have a look. Also, since I needed this right away in a project, I published an NPM package with the feature:
Hopefully both |
Hey @OskarAsplin, thank you so much for sending in that PR. I think it looks great, I just had one very small comment. Also, apologies for creating this PR and then disappearing. I had a baby and life took over 😅 But I would love to move this forward if @ferdikoomen is open to the changes we're proposing. |
@petrgazarov do the changes in OskarAsplin's version give you what you need for the service response bodies? |
ed3d488
to
d2fc59f
Compare
Hi @ferdikoomen I wanted to check in to see if you've had time to think about this PR? I'd love to get it merged and am willing to continue to help maintain it if folks have issues. |
@OskarAsplin I discovered a bug in the PR that I've just fixed. If a string looked like |
@robdodson thanks for merging my stuff and continuing to work on this! It looks like you included generated code in the last commit though. See all the added files in the Also, I found out two other things:
// Without convertEnumCase
export enum format {
JSON_V1_1 = 'json_v1.1',
IMAGE_PNG = 'image_png',
}
// With convertEnumCase - notice JSON_V11
export enum format {
JSON_V11 = 'json_v1.1',
IMAGE_PNG = 'image_png',
}
|
@OskarAsplin thank you for the feedback, I'll get this all fixed up! |
598111c
to
67b5def
Compare
@robdodson our team is really looking forward to this feature. Thanks for taking it on! |
Found another minor issue. If a request body is defined directly in the endpoint (not just a reference to a schema) it will not be case converted. It just needs a simple one liner to fix it. I fixed it in a fork I have c1e1098 @robdodson please take a look and add it here if you have time :) |
Apologies for being slow on this. I've started looking into Zodios and /~https://github.com/astahmer/openapi-zod-client and may switch over to that. But I will try to update this PR with the latest when I get a chance so other folks can keep using it. |
I've filed an issue on the openapi-ts repo to see if they would accept this PR |
What changed
Adds a
--transformCase
flag that accepts eithersnake
orcamel
(defaults tonone
). Will convert model names from snake, camel, or pascal case to whichever option was passed in.For example, if the original file was in pascal case:
--transformCase camel
--transformCase snake
Why the change was made
Much like the original requester in #1252, our company has a large API that returns keys in snake case, but we convert them to camel case on the frontend using a bit of middleware in our fetch functions. The types generated from our OpenAPI specs are in snake case, which means we can't use them.
@ferdikoomen Is this feature something you'd consider incorporating? If so I'd be happy to add additional tests and make any changes you think are needed.