fix(packages/nhost-js): react native needs special treatment when using FormData (#3697)
Co-authored-by: dbarrosop <dbarrosop@users.noreply.github.com>
This commit is contained in:
@@ -3,8 +3,14 @@ table:
|
|||||||
schema: auth
|
schema: auth
|
||||||
is_enum: true
|
is_enum: true
|
||||||
configuration:
|
configuration:
|
||||||
column_config: {}
|
column_config:
|
||||||
custom_column_names: {}
|
comment:
|
||||||
|
custom_name: comment
|
||||||
|
value:
|
||||||
|
custom_name: value
|
||||||
|
custom_column_names:
|
||||||
|
comment: comment
|
||||||
|
value: value
|
||||||
custom_name: authRefreshTokenTypes
|
custom_name: authRefreshTokenTypes
|
||||||
custom_root_fields:
|
custom_root_fields:
|
||||||
delete: deleteAuthRefreshTokenTypes
|
delete: deleteAuthRefreshTokenTypes
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ httpPoolSize = 100
|
|||||||
version = 22
|
version = 22
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
version = '0.41.1'
|
version = '0.43.1'
|
||||||
|
|
||||||
[auth.elevatedPrivileges]
|
[auth.elevatedPrivileges]
|
||||||
mode = 'disabled'
|
mode = 'disabled'
|
||||||
@@ -183,7 +183,7 @@ capacity = 1
|
|||||||
[provider]
|
[provider]
|
||||||
|
|
||||||
[storage]
|
[storage]
|
||||||
version = '0.8.0-beta5'
|
version = '0.9.1'
|
||||||
|
|
||||||
[observability]
|
[observability]
|
||||||
[observability.grafana]
|
[observability.grafana]
|
||||||
|
|||||||
@@ -154,6 +154,11 @@ export default function Files() {
|
|||||||
const response = await nhost.storage.uploadFiles({
|
const response = await nhost.storage.uploadFiles({
|
||||||
"bucket-id": "personal",
|
"bucket-id": "personal",
|
||||||
"file[]": [file as File],
|
"file[]": [file as File],
|
||||||
|
"metadata[]": [
|
||||||
|
{
|
||||||
|
metadata: { key1: "value1" },
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get the processed file data
|
// Get the processed file data
|
||||||
|
|||||||
@@ -467,7 +467,12 @@ export default function Todos() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{showAddForm && (
|
{showAddForm && (
|
||||||
<View style={[commonStyles.card, { marginHorizontal: 16, width: undefined }]}>
|
<View
|
||||||
|
style={[
|
||||||
|
commonStyles.card,
|
||||||
|
{ marginHorizontal: 16, width: undefined },
|
||||||
|
]}
|
||||||
|
>
|
||||||
<Text style={commonStyles.cardTitle}>Add New Todo</Text>
|
<Text style={commonStyles.cardTitle}>Add New Todo</Text>
|
||||||
<View style={commonStyles.formFields}>
|
<View style={commonStyles.formFields}>
|
||||||
<View style={commonStyles.fieldGroup}>
|
<View style={commonStyles.fieldGroup}>
|
||||||
|
|||||||
@@ -17,9 +17,11 @@
|
|||||||
"expo-crypto": "14",
|
"expo-crypto": "14",
|
||||||
"expo-document-picker": "13",
|
"expo-document-picker": "13",
|
||||||
"expo-file-system": "18",
|
"expo-file-system": "18",
|
||||||
|
"expo-linking": "^8.0.8",
|
||||||
"expo-router": "~6",
|
"expo-router": "~6",
|
||||||
"expo-sharing": "13",
|
"expo-sharing": "13",
|
||||||
"expo-status-bar": "~3.0.8",
|
"expo-status-bar": "~3.0.8",
|
||||||
|
"metro-minify-terser": "^0.83.3",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-native": "0.81.4"
|
"react-native": "0.81.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ importers:
|
|||||||
expo-file-system:
|
expo-file-system:
|
||||||
specifier: '18'
|
specifier: '18'
|
||||||
version: 18.1.11(expo@54.0.9)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))
|
version: 18.1.11(expo@54.0.9)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))
|
||||||
|
expo-linking:
|
||||||
|
specifier: ^8.0.8
|
||||||
|
version: 8.0.8(expo@54.0.9)(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0)
|
||||||
expo-router:
|
expo-router:
|
||||||
specifier: ~6
|
specifier: ~6
|
||||||
version: 6.0.7(@expo/metro-runtime@6.1.2)(@types/react@19.1.13)(expo-constants@18.0.9)(expo-linking@8.0.8)(expo@54.0.9)(react-dom@19.1.1(react@19.1.0))(react-native-safe-area-context@5.6.1(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0)
|
version: 6.0.7(@expo/metro-runtime@6.1.2)(@types/react@19.1.13)(expo-constants@18.0.9)(expo-linking@8.0.8)(expo@54.0.9)(react-dom@19.1.1(react@19.1.0))(react-native-safe-area-context@5.6.1(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0)
|
||||||
@@ -41,6 +44,9 @@ importers:
|
|||||||
expo-status-bar:
|
expo-status-bar:
|
||||||
specifier: ~3.0.8
|
specifier: ~3.0.8
|
||||||
version: 3.0.8(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0)
|
version: 3.0.8(react-native@0.81.4(@babel/core@7.28.4)(@types/react@19.1.13)(react@19.1.0))(react@19.1.0)
|
||||||
|
metro-minify-terser:
|
||||||
|
specifier: ^0.83.3
|
||||||
|
version: 0.83.3
|
||||||
react:
|
react:
|
||||||
specifier: 19.1.0
|
specifier: 19.1.0
|
||||||
version: 19.1.0
|
version: 19.1.0
|
||||||
@@ -2232,6 +2238,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-zvIxnh7U0JQ7vT4quasKsijId3dOAWgq+ip2jF/8TMrPUqQabGrs04L2dd0haQJ+PA+d4VvK/bPOY8X/vL2PWw==}
|
resolution: {integrity: sha512-zvIxnh7U0JQ7vT4quasKsijId3dOAWgq+ip2jF/8TMrPUqQabGrs04L2dd0haQJ+PA+d4VvK/bPOY8X/vL2PWw==}
|
||||||
engines: {node: '>=20.19.4'}
|
engines: {node: '>=20.19.4'}
|
||||||
|
|
||||||
|
metro-minify-terser@0.83.3:
|
||||||
|
resolution: {integrity: sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ==}
|
||||||
|
engines: {node: '>=20.19.4'}
|
||||||
|
|
||||||
metro-resolver@0.83.1:
|
metro-resolver@0.83.1:
|
||||||
resolution: {integrity: sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g==}
|
resolution: {integrity: sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g==}
|
||||||
engines: {node: '>=20.19.4'}
|
engines: {node: '>=20.19.4'}
|
||||||
@@ -5840,6 +5850,11 @@ snapshots:
|
|||||||
flow-enums-runtime: 0.0.6
|
flow-enums-runtime: 0.0.6
|
||||||
terser: 5.44.0
|
terser: 5.44.0
|
||||||
|
|
||||||
|
metro-minify-terser@0.83.3:
|
||||||
|
dependencies:
|
||||||
|
flow-enums-runtime: 0.0.6
|
||||||
|
terser: 5.44.0
|
||||||
|
|
||||||
metro-resolver@0.83.1:
|
metro-resolver@0.83.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
flow-enums-runtime: 0.0.6
|
flow-enums-runtime: 0.0.6
|
||||||
|
|||||||
@@ -632,16 +632,27 @@ export const createAPIClient = (
|
|||||||
): Promise<FetchResponse<UploadFilesResponse201>> => {
|
): Promise<FetchResponse<UploadFilesResponse201>> => {
|
||||||
const url = `${baseURL}/files`;
|
const url = `${baseURL}/files`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
const isReactNative =
|
||||||
|
typeof navigator !== "undefined" &&
|
||||||
|
(navigator as { product?: string }).product === "ReactNative";
|
||||||
if (body["bucket-id"] !== undefined) {
|
if (body["bucket-id"] !== undefined) {
|
||||||
formData.append("bucket-id", body["bucket-id"]);
|
formData.append("bucket-id", body["bucket-id"]);
|
||||||
}
|
}
|
||||||
if (body["metadata[]"] !== undefined) {
|
if (body["metadata[]"] !== undefined) {
|
||||||
body["metadata[]"].forEach((value) => {
|
body["metadata[]"].forEach((value) => {
|
||||||
formData.append(
|
if (isReactNative) {
|
||||||
"metadata[]",
|
formData.append("metadata[]", {
|
||||||
new Blob([JSON.stringify(value)], { type: "application/json" }),
|
string: JSON.stringify(value),
|
||||||
"",
|
type: "application/json",
|
||||||
);
|
name: "",
|
||||||
|
} as unknown as Blob);
|
||||||
|
} else {
|
||||||
|
formData.append(
|
||||||
|
"metadata[]",
|
||||||
|
new Blob([JSON.stringify(value)], { type: "application/json" }),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (body["file[]"] !== undefined) {
|
if (body["file[]"] !== undefined) {
|
||||||
@@ -799,14 +810,25 @@ export const createAPIClient = (
|
|||||||
): Promise<FetchResponse<FileMetadata>> => {
|
): Promise<FetchResponse<FileMetadata>> => {
|
||||||
const url = `${baseURL}/files/${id}`;
|
const url = `${baseURL}/files/${id}`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
const isReactNative =
|
||||||
|
typeof navigator !== "undefined" &&
|
||||||
|
(navigator as { product?: string }).product === "ReactNative";
|
||||||
if (body["metadata"] !== undefined) {
|
if (body["metadata"] !== undefined) {
|
||||||
formData.append(
|
if (isReactNative) {
|
||||||
"metadata",
|
formData.append("metadata", {
|
||||||
new Blob([JSON.stringify(body["metadata"])], {
|
string: JSON.stringify(body["metadata"]),
|
||||||
type: "application/json",
|
type: "application/json",
|
||||||
}),
|
name: "",
|
||||||
"",
|
} as unknown as Blob);
|
||||||
);
|
} else {
|
||||||
|
formData.append(
|
||||||
|
"metadata",
|
||||||
|
new Blob([JSON.stringify(body["metadata"])], {
|
||||||
|
type: "application/json",
|
||||||
|
}),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (body["file"] !== undefined) {
|
if (body["file"] !== undefined) {
|
||||||
formData.append("file", body["file"]);
|
formData.append("file", body["file"]);
|
||||||
|
|||||||
@@ -767,16 +767,30 @@ export const createAPIClient = (
|
|||||||
): Promise<FetchResponse<UploadFilesResponse201>> => {
|
): Promise<FetchResponse<UploadFilesResponse201>> => {
|
||||||
const url = `${ baseURL }/files/`;
|
const url = `${ baseURL }/files/`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
const isReactNative =
|
||||||
|
typeof navigator !== "undefined" &&
|
||||||
|
(navigator as { product?: string }).product === "ReactNative";
|
||||||
if (body["bucket-id"] !== undefined) {
|
if (body["bucket-id"] !== undefined) {
|
||||||
formData.append("bucket-id", body["bucket-id"]);
|
formData.append("bucket-id", body["bucket-id"]);
|
||||||
}
|
}
|
||||||
if (body["metadata[]"] !== undefined) {
|
if (body["metadata[]"] !== undefined) {
|
||||||
body["metadata[]"].forEach((value) => {
|
body["metadata[]"].forEach((value) => {
|
||||||
formData.append(
|
if (isReactNative) {
|
||||||
|
formData.append(
|
||||||
|
"metadata[]",
|
||||||
|
{
|
||||||
|
string: JSON.stringify(value),
|
||||||
|
type: "application/json",
|
||||||
|
name: "",
|
||||||
|
} as unknown as Blob,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
formData.append(
|
||||||
"metadata[]",
|
"metadata[]",
|
||||||
new Blob([JSON.stringify(value)], { type: "application/json" }),
|
new Blob([JSON.stringify(value)], { type: "application/json" }),
|
||||||
"",
|
"",
|
||||||
)
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -912,12 +926,26 @@ export const createAPIClient = (
|
|||||||
): Promise<FetchResponse<FileMetadata>> => {
|
): Promise<FetchResponse<FileMetadata>> => {
|
||||||
const url = `${ baseURL }/files/${id}`;
|
const url = `${ baseURL }/files/${id}`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
const isReactNative =
|
||||||
|
typeof navigator !== "undefined" &&
|
||||||
|
(navigator as { product?: string }).product === "ReactNative";
|
||||||
if (body["metadata"] !== undefined) {
|
if (body["metadata"] !== undefined) {
|
||||||
formData.append(
|
if (isReactNative) {
|
||||||
|
formData.append(
|
||||||
|
"metadata",
|
||||||
|
{
|
||||||
|
string: JSON.stringify(body["metadata"]),
|
||||||
|
type: "application/json",
|
||||||
|
name: "",
|
||||||
|
} as unknown as Blob,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
formData.append(
|
||||||
"metadata",
|
"metadata",
|
||||||
new Blob([JSON.stringify(body["metadata"])], { type: "application/json" }),
|
new Blob([JSON.stringify(body["metadata"])], { type: "application/json" }),
|
||||||
"",
|
"",
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (body["file"] !== undefined) {
|
if (body["file"] !== undefined) {
|
||||||
formData.append("file", body["file"]);
|
formData.append("file", body["file"]);
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ export const createAPIClient = (
|
|||||||
});
|
});
|
||||||
{{- else if .RequestFormData }}
|
{{- else if .RequestFormData }}
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
const isReactNative =
|
||||||
|
typeof navigator !== "undefined" &&
|
||||||
|
(navigator as { product?: string }).product === "ReactNative";
|
||||||
|
|
||||||
{{- range .RequestFormData.Properties }}
|
{{- range .RequestFormData.Properties }}
|
||||||
{{- if eq .Type.Kind "scalar" }}
|
{{- if eq .Type.Kind "scalar" }}
|
||||||
@@ -138,11 +141,22 @@ export const createAPIClient = (
|
|||||||
{{- if eq .Type.Item.Kind "scalar" }}
|
{{- if eq .Type.Item.Kind "scalar" }}
|
||||||
formData.append("{{ .Name }}", value)
|
formData.append("{{ .Name }}", value)
|
||||||
{{- else if eq .Type.Item.Kind "object" }}
|
{{- else if eq .Type.Item.Kind "object" }}
|
||||||
formData.append(
|
if (isReactNative) {
|
||||||
|
formData.append(
|
||||||
|
"{{ .Name }}",
|
||||||
|
{
|
||||||
|
string: JSON.stringify(value),
|
||||||
|
type: "application/json",
|
||||||
|
name: "",
|
||||||
|
} as unknown as Blob,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
formData.append(
|
||||||
"{{ .Name }}",
|
"{{ .Name }}",
|
||||||
new Blob([JSON.stringify(value)], { type: "application/json" }),
|
new Blob([JSON.stringify(value)], { type: "application/json" }),
|
||||||
"",
|
"",
|
||||||
)
|
);
|
||||||
|
}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
TODO {{ .Type.Kind }} {{ .Type.Schema.Schema.Type }}
|
TODO {{ .Type.Kind }} {{ .Type.Schema.Schema.Type }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -151,11 +165,22 @@ export const createAPIClient = (
|
|||||||
}
|
}
|
||||||
{{- else if eq .Type.Kind "object" }}
|
{{- else if eq .Type.Kind "object" }}
|
||||||
if (body["{{ .Name }}"] !== undefined) {
|
if (body["{{ .Name }}"] !== undefined) {
|
||||||
formData.append(
|
if (isReactNative) {
|
||||||
|
formData.append(
|
||||||
|
"{{ .Name }}",
|
||||||
|
{
|
||||||
|
string: JSON.stringify(body["{{ .Name }}"]),
|
||||||
|
type: "application/json",
|
||||||
|
name: "",
|
||||||
|
} as unknown as Blob,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
formData.append(
|
||||||
"{{ .Name }}",
|
"{{ .Name }}",
|
||||||
new Blob([JSON.stringify(body["{{ .Name }}"])], { type: "application/json" }),
|
new Blob([JSON.stringify(body["{{ .Name }}"])], { type: "application/json" }),
|
||||||
"",
|
"",
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
TODO {{ .Type.Kind }} {{ .Type.Schema.Schema.Type }}
|
TODO {{ .Type.Kind }} {{ .Type.Schema.Schema.Type }}
|
||||||
|
|||||||
Reference in New Issue
Block a user