From cee8588d83c3c9313aebf49d1d2f8d99ed0a8617 Mon Sep 17 00:00:00 2001 From: nd0ut Date: Thu, 11 Mar 2021 10:51:09 +0300 Subject: [PATCH 1/3] fix: support direct uploads through FormData under react-native runtime --- package.json | 9 +++++++-- src/tools/buildFormData.ts | 18 ++++++++++-------- src/tools/getFormData.browser.ts | 4 ++++ src/tools/getFormData.node.ts | 3 +++ src/tools/getFormData.react-native.ts | 16 ++++++++++++++++ src/tools/identity.ts | 3 +++ src/tools/types.ts | 8 ++++++++ 7 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/tools/getFormData.react-native.ts create mode 100644 src/tools/identity.ts create mode 100644 src/tools/types.ts diff --git a/package.json b/package.json index c3aebf760..21f493d8d 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,11 @@ "./lib/tools/getFormData.node.js": "./lib/tools/getFormData.browser.js", "./lib/tools/sockets.node.js": "./lib/tools/sockets.browser.js" }, + "react-native": { + "./lib/request/request.node.js": "./lib/request/request.browser.js", + "./lib/tools/getFormData.node.js": "./lib/tools/getFormData.react-native.js", + "./lib/tools/sockets.node.js": "./lib/tools/sockets.browser.js" + }, "scripts": { "check-env-vars": "node ./checkvars.js", "mock:start": "ts-node --project ./mock-server/tsconfig.mock.json ./mock-server/server.ts --silent", @@ -52,9 +57,9 @@ "@types/koa": "2.11.4", "@types/node": "12.12.67", "@types/promise": "7.1.30", + "@types/ws": "7.2.7", "@typescript-eslint/eslint-plugin": "2.34.0", "@typescript-eslint/parser": "2.34.0", - "@types/ws": "7.2.7", "chalk": "4.1.0", "data-uri-to-buffer": "3.0.1", "dataurl-to-blob": "0.0.1", @@ -74,8 +79,8 @@ "rimraf": "3.0.2", "shipjs": "0.22.0", "start-server-and-test": "1.11.5", - "ts-node": "8.10.2", "ts-jest": "26.4.1", + "ts-node": "8.10.2", "typescript": "3.9.7" }, "dependencies": { diff --git a/src/tools/buildFormData.ts b/src/tools/buildFormData.ts index 4f20e7125..a8cb4bdb6 100644 --- a/src/tools/buildFormData.ts +++ b/src/tools/buildFormData.ts @@ -1,4 +1,4 @@ -import getFormData from './getFormData.node' +import getFormData, { transformFile } from './getFormData.node' import * as NodeFormData from 'form-data' import { BrowserFile, NodeFile } from '../request/types' @@ -9,24 +9,26 @@ import { BrowserFile, NodeFile } from '../request/types' * in browsers. */ -type FileTuple = ['file', BrowserFile | NodeFile, string] +type FileTriple = ['file', BrowserFile | NodeFile, string] type BaseType = string | number | void type FormDataTuple = [string, BaseType | BaseType[]] +const isFileTriple = (tuple: FormDataTuple | FileTriple): tuple is FileTriple => + tuple[0] === 'file' + function buildFormData( - body: (FormDataTuple | FileTuple)[] + body: (FormDataTuple | FileTriple)[] ): FormData | NodeFormData { const formData = getFormData() - const isTriple = (tuple: FormDataTuple | FileTuple): tuple is FileTuple => - tuple[0] === 'file' - for (const tuple of body) { if (Array.isArray(tuple[1])) { // refactor this tuple[1].forEach(val => val && formData.append(tuple[0] + '[]', `${val}`)) - } else if (isTriple(tuple)) { - formData.append(tuple[0], tuple[1] as Blob, tuple[2]) + } else if (isFileTriple(tuple)) { + const name = tuple[2] + const file = transformFile(tuple[1], name) as Blob + formData.append(tuple[0], file, name) } else if (tuple[1] != null) { formData.append(tuple[0], `${tuple[1]}`) } diff --git a/src/tools/getFormData.browser.ts b/src/tools/getFormData.browser.ts index b2c430690..b74b18f2b 100644 --- a/src/tools/getFormData.browser.ts +++ b/src/tools/getFormData.browser.ts @@ -1 +1,5 @@ +import { FileTransformer } from './types' +import { identity } from './identity' + +export const transformFile: FileTransformer = identity export default (): FormData => new FormData() diff --git a/src/tools/getFormData.node.ts b/src/tools/getFormData.node.ts index 86233d026..40d9552c1 100644 --- a/src/tools/getFormData.node.ts +++ b/src/tools/getFormData.node.ts @@ -1,3 +1,6 @@ import * as NodeFormData from 'form-data' +import { FileTransformer } from './types' +import { identity } from './identity' +export const transformFile: FileTransformer = identity export default (): NodeFormData | FormData => new NodeFormData() diff --git a/src/tools/getFormData.react-native.ts b/src/tools/getFormData.react-native.ts new file mode 100644 index 000000000..38ea95dbb --- /dev/null +++ b/src/tools/getFormData.react-native.ts @@ -0,0 +1,16 @@ +import { BrowserFile, NodeFile } from '../request/types' +import { FileTransformer, ReactNativeAsset } from './types' + +export const transformFile: FileTransformer = ( + file: BrowserFile | NodeFile, + name: string +): ReactNativeAsset => { + if (!file) { + return file + } + const uri = URL.createObjectURL(file) + const type = (file as BrowserFile).type + return { uri, name, type } +} + +export default (): FormData => new FormData() diff --git a/src/tools/identity.ts b/src/tools/identity.ts new file mode 100644 index 000000000..5a3e228b8 --- /dev/null +++ b/src/tools/identity.ts @@ -0,0 +1,3 @@ +export function identity(obj: T): T { + return obj +} diff --git a/src/tools/types.ts b/src/tools/types.ts new file mode 100644 index 000000000..5fbc6adfe --- /dev/null +++ b/src/tools/types.ts @@ -0,0 +1,8 @@ +import { BrowserFile, NodeFile } from '../request/types' + +export type ReactNativeAsset = { name?: string; type?: string; uri: string } + +export type FileTransformer = ( + file: NodeFile | BrowserFile, + name: string +) => NodeFile | BrowserFile | ReactNativeAsset From 43c50a433ca9bbf43329e01a08869b8b61b5b2b8 Mon Sep 17 00:00:00 2001 From: nd0ut Date: Thu, 11 Mar 2021 13:01:01 +0300 Subject: [PATCH 2/3] chore: ignore lgtm warning --- src/tools/buildFormData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/buildFormData.ts b/src/tools/buildFormData.ts index a8cb4bdb6..37cc522f1 100644 --- a/src/tools/buildFormData.ts +++ b/src/tools/buildFormData.ts @@ -27,7 +27,7 @@ function buildFormData( tuple[1].forEach(val => val && formData.append(tuple[0] + '[]', `${val}`)) } else if (isFileTriple(tuple)) { const name = tuple[2] - const file = transformFile(tuple[1], name) as Blob + const file = transformFile(tuple[1], name) as Blob // lgtm[js/superfluous-trailing-arguments] formData.append(tuple[0], file, name) } else if (tuple[1] != null) { formData.append(tuple[0], `${tuple[1]}`) From be65ca09b90a226b8ebcb022cbe0d5b211cda718 Mon Sep 17 00:00:00 2001 From: nd0ut Date: Tue, 16 Mar 2021 19:23:58 +0300 Subject: [PATCH 3/3] chore: dont use word 'triple' in variable name --- src/tools/buildFormData.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/buildFormData.ts b/src/tools/buildFormData.ts index 37cc522f1..381384a36 100644 --- a/src/tools/buildFormData.ts +++ b/src/tools/buildFormData.ts @@ -9,15 +9,15 @@ import { BrowserFile, NodeFile } from '../request/types' * in browsers. */ -type FileTriple = ['file', BrowserFile | NodeFile, string] +type FileTuple = ['file', BrowserFile | NodeFile, string] type BaseType = string | number | void type FormDataTuple = [string, BaseType | BaseType[]] -const isFileTriple = (tuple: FormDataTuple | FileTriple): tuple is FileTriple => +const isFileTuple = (tuple: FormDataTuple | FileTuple): tuple is FileTuple => tuple[0] === 'file' function buildFormData( - body: (FormDataTuple | FileTriple)[] + body: (FormDataTuple | FileTuple)[] ): FormData | NodeFormData { const formData = getFormData() @@ -25,7 +25,7 @@ function buildFormData( if (Array.isArray(tuple[1])) { // refactor this tuple[1].forEach(val => val && formData.append(tuple[0] + '[]', `${val}`)) - } else if (isFileTriple(tuple)) { + } else if (isFileTuple(tuple)) { const name = tuple[2] const file = transformFile(tuple[1], name) as Blob // lgtm[js/superfluous-trailing-arguments] formData.append(tuple[0], file, name)