Skip to content
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

Add support for React Native in @TypedFormData.Body() #1018

Closed
omaziarz opened this issue Sep 5, 2024 · 8 comments
Closed

Add support for React Native in @TypedFormData.Body() #1018

omaziarz opened this issue Sep 5, 2024 · 8 comments
Assignees
Labels
enhancement New feature or request good first issue Good for newcomers question Further information is requested

Comments

@omaziarz
Copy link

omaziarz commented Sep 5, 2024

Feature Request

In react native the only way to send Files in a multipart request is by doing the following :

const formdata = new FormData();
formdata.append('file', {
  uri: 'path-to-file-on-the-phone',
  name: 'file-name',
  type: 'image/png',
});

this doesn't work :

formdata.append('file', new Blob(...))
formdata.append('file', new File(...))

As expected when using the first approach I will get the following error when using the custom object:

[Error: {"path":"$input.file","reason":"Error on typia.http.assertFormData(): invalid type on $input.file, expect to be Blob","expected":"Blob","value":"[object Object]","message":"Request multipart data is not following the promised type."}]

I think that to support all environments, validation inside @TypedFormData.Body() should support the custom object as a valid Blob because, at least, in fastify the custom object works the same way as a Blob without any additional handling needed

//this is not of type Blob but it works when sent to fastify
{
  uri: 'path-to-file-on-the-phone',
  name: 'file-name',
  type: 'image/png',
}
@samchon
Copy link
Owner

samchon commented Sep 10, 2024

I have a question. Is it really okay just by writinng the string path? It actually converted to the File instance?

Can you show me an example creating the FormData instance in the React Native with exact type?

I want to know about below type exactly. Is it really okay with primitive object instance? Or needs another class type?

{
  uri: 'path-to-file-on-the-phone',
  name: 'file-name',
  type: 'image/png',
}

@samchon samchon self-assigned this Sep 10, 2024
@samchon samchon added the question Further information is requested label Sep 10, 2024
@omaziarz
Copy link
Author

yes sure

React-Native

import { SafeAreaView, Button } from 'react-native';

export default function HomeScreen() {
  const handlePress = async () => {
    const body = new FormData();
    body.append('file', {
      name: 'image.png',
      type: 'image/png',
      uri: 'https://picsum.photos/500/500', // this can be any uri so local phone uri or internet
    });

    fetch('http://192.168.0.106:3050/upload', {
      method: 'POST',
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      body,
    });
  };

  return (
    <SafeAreaView
      style={{
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        gap: 100,
      }}
    >
      <Button title="changePP" onPress={handlePress} />
    </SafeAreaView>
  );
}

Fastify Server

import fastify from 'fastify';
import multipart from '@fastify/multipart';
const server = fastify();

server.register(multipart);

server.post('/upload', async (req, res) => {
  const file = await req.file();

  console.log((await file?.toBuffer())?.byteLength);
});

server.listen({
  port: 3050,
  host: '0.0.0.0',
});

The value of console.log((await file?.toBuffer())?.byteLength); will be > 0, fastify handles it without any added logic

@samchon
Copy link
Owner

samchon commented Sep 10, 2024

In the @nestia/sdk, both client and server side must have the same type.

Therefore, I don't know how to solve this problem especially for the React Native.

For a while, how about solving this problem by hard casting to the File class in the RN client side?

I will consider the adapt the File | IFileUri type in the @TypedFormData.Body() decorator, but need your suggestion.

@omaziarz
Copy link
Author

what do you mean by hard casting ? using the as keyword ?

If the File | IFileUri solution is doable for you then IFileUri should be the following :

interface IFileUri {
  uri: string;
  name: string;
  type: string; 
}

these are the only required properties.

@samchon
Copy link
Owner

samchon commented Sep 17, 2024

I'll solve this problem by making below type.

By the way, I'm considering below type names.

@omaziarz, will you determine the type name?

  • FormDataInput
  • FormDataRequest
  • FormDataProps
export type FormDataInput<T extends object> =
  T extends Array<any>
    ? never
    : T extends Function
      ? never
      : {
          [P in keyof T]: T[P] extends Array<infer U>
            ? FormDataValue<U>[]
            : FormDataValue<T[P]>;
        };

type FormDataValue<T> = T extends File ? T | FileProps : T;

interface FileProps {
  uri: string;
  name: string;
  type: string;
}

@samchon samchon added enhancement New feature or request good first issue Good for newcomers labels Sep 17, 2024
@omaziarz
Copy link
Author

I'll solve this problem by making below type.

By the way, I'm considering below type names.

@omaziarz, will you determine the type name?

  • FormDataInput
  • FormDataRequest
  • FormDataProps
export type FormDataInput<T extends object> =
  T extends Array<any>
    ? never
    : T extends Function
      ? never
      : {
          [P in keyof T]: T[P] extends Array<infer U>
            ? FormDataValue<U>[]
            : FormDataValue<T[P]>;
        };

type FormDataValue<T> = T extends File ? T | FileProps : T;

interface FileProps {
  uri: string;
  name: string;
  type: string;
}

Well i'm not really good with names myself haha but FormDataInput sounds good to me.
And hit me up when you need me to test it before publishing a new version.
Thanks for your reactivity :)

samchon added a commit to samchon/openapi that referenced this issue Sep 17, 2024
Fix samchon/nestia#1018: `HttpMigrateRouteFetcher` for React Native.
@samchon samchon reopened this Sep 17, 2024
samchon added a commit that referenced this issue Sep 17, 2024
Fix #1018: add `FormDataInput<T>` type for React Native environment.
@samchon
Copy link
Owner

samchon commented Sep 17, 2024

Upgrade to latest. Would works properly.

@omaziarz
Copy link
Author

@samchon just to confirm with you that it works thank you very much !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers question Further information is requested
Projects
Status: Done
Development

No branches or pull requests

2 participants