diff --git a/HACKS.md b/HACKS.md index 947a2e8121b..f887e5a67be 100644 --- a/HACKS.md +++ b/HACKS.md @@ -161,16 +161,6 @@ There are two hacks here: - We hack the output of the compiler to provide clickable links for error messages. Relay assumes that you put your `__generated__` folder in the root of your project, but we put it in `src`. - We make sure that files which do not change are not overwritten. This prevents excessive reloading by metro. -## react-relay-network-modern (upload middleware patch) - -#### When can we remove this: - -We can remove this hack when we can pass Blob/File with specified `name` field to `fetch()` and we won't get an error on Android - -#### Explanation/Context: - -If we try to pass Blob/File with specified `name` field (if we forgot to specify this field, Metaphysics will assume that no file was passed) to `fetch()`, we will get an error on Android. For this reason, support for these data formats is extracted from `upload` middleware. - ## react-native-credit-card-input #### When can we remove this: diff --git a/package.json b/package.json index 7589ee55844..a575496b24e 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,6 @@ "deprecated-react-native-prop-types": "4.1.0", "easy-peasy": "6.0.0", "events": "3.3.0", - "extract-files": "9.0.0", "formik": "2.2.9", "google-libphonenumber": "3.2.33", "grapheme-splitter": "1.0.4", @@ -236,7 +235,6 @@ "@types/autosuggest-highlight": "3.1.1", "@types/chalk": "2.2.0", "@types/dedent": "0.7.0", - "@types/extract-files": "8.1.1", "@types/google-libphonenumber": "7.4.26", "@types/jest": "29.2.6", "@types/jscodeshift": "0.11.6", diff --git a/patches/@types+extract-files+8.1.1.patch b/patches/@types+extract-files+8.1.1.patch deleted file mode 100644 index 8fbf08b23bd..00000000000 --- a/patches/@types+extract-files+8.1.1.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/node_modules/@types/extract-files/index.d.ts b/node_modules/@types/extract-files/index.d.ts -index c329089..854c552 100755 ---- a/node_modules/@types/extract-files/index.d.ts -+++ b/node_modules/@types/extract-files/index.d.ts -@@ -7,13 +7,13 @@ - export interface ReactNativeFileOptions { - uri: string; - type?: string | undefined; -- name?: string | undefined; -+ name: string; - } - - export class ReactNativeFile { - uri: string; - type?: string | undefined; -- name?: string | undefined; -+ name: string; - - constructor(options: ReactNativeFileOptions); - } diff --git a/src/app/system/relay/defaultEnvironment.ts b/src/app/system/relay/defaultEnvironment.ts index 7dc7eb98713..7213a1e0996 100644 --- a/src/app/system/relay/defaultEnvironment.ts +++ b/src/app/system/relay/defaultEnvironment.ts @@ -2,6 +2,7 @@ import { Environment as IEnvironment } from "react-relay" import { errorMiddleware as relayErrorMiddleware, RelayNetworkLayer, + uploadMiddleware, } from "react-relay-network-modern/node8" import { Environment, RecordSource, Store } from "relay-runtime" import { MockEnvironment } from "relay-test-utils" @@ -17,7 +18,6 @@ import { import { rateLimitMiddleware } from "./middlewares/rateLimitMiddleware" import { simpleLoggerMiddleware } from "./middlewares/simpleLoggerMiddleware" import { timingMiddleware } from "./middlewares/timingMiddleware" -import { uploadMiddleware } from "./middlewares/uploadMiddleware" const network = new RelayNetworkLayer( [ diff --git a/src/app/system/relay/middlewares/uploadMiddleware.tests.ts b/src/app/system/relay/middlewares/uploadMiddleware.tests.ts deleted file mode 100644 index 1cbee237965..00000000000 --- a/src/app/system/relay/middlewares/uploadMiddleware.tests.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { ReactNativeFile } from "extract-files" -import { RelayNetworkLayerResponse } from "react-relay-network-modern/node8" -import { GraphQLRequest } from "./types" -import { uploadMiddleware } from "./uploadMiddleware" - -describe("uploadMiddleware", () => { - const mockAppend = jest.fn() - - // @ts-expect-error - global.FormData = function () { - // @ts-expect-error - this.append = mockAppend - } - - const fileOne = new ReactNativeFile({ - uri: "/path/to/file/filename-one.jpg", - name: "filename-one.jpg", - type: "image/jpeg", - }) - - const fileTwo = new ReactNativeFile({ - uri: "/path/to/file/filename-two.jpg", - name: "filename-two.jpg", - type: "image/jpeg", - }) - - const relayResponse: RelayNetworkLayerResponse = { - _res: null, - ok: true, - status: 200, - json: {}, - processJsonData: () => ({}), - clone: () => relayResponse, - } - - const middleware = uploadMiddleware() - const mockNext = jest.fn().mockImplementation(() => Promise.resolve(relayResponse)) - - const request: GraphQLRequest = { - // @ts-ignore - operation: { - operationKind: "query", - text: "", - }, - variables: { - file: fileOne, - }, - fetchOpts: { - method: "POST", - body: "", - headers: { - "Content-Type": "application/json", - "User-Agent": "user-agent-value", - "X-USER-ID": "user-id", - "X-TIMEZONE": "Europe/Berlin", - }, - }, - } - - beforeEach(() => { - mockNext.mockClear() - mockAppend.mockClear() - }) - - it("`body` field is an instance of FormData", () => { - middleware(mockNext)(request) - const call = mockNext.mock.calls[0][0] - const formData = call.fetchOpts.body - - expect(formData).toBeInstanceOf(FormData) - }) - - it("should be appended specific fields for FormData", () => { - middleware(mockNext)(request) - const call = mockAppend.mock.calls - - expect(call[0][0]).toBe("operations") - expect(call[1][0]).toBe("map") - - // File - expect(call[2][0]).toBe("0") - expect(call[2][1]).toMatchInlineSnapshot(` - ReactNativeFile { - "name": "filename-one.jpg", - "type": "image/jpeg", - "uri": "/path/to/file/filename-one.jpg", - } - `) - }) - - it("should be possible to specify multiple files", () => { - const requestWithMultipleFiles: GraphQLRequest = { - // @ts-ignore - operation: { - operationKind: "query", - text: "", - }, - variables: { - files: [fileOne, fileTwo], - }, - fetchOpts: { - method: "POST", - body: "", - headers: { - "Content-Type": "application/json", - "User-Agent": "user-agent-value", - "X-USER-ID": "user-id", - "X-TIMEZONE": "Europe/Berlin", - }, - }, - } - - middleware(mockNext)(requestWithMultipleFiles) - const call = mockAppend.mock.calls - - expect(call[0][0]).toBe("operations") - expect(call[1][0]).toBe("map") - - // First file - expect(call[2][0]).toBe("0") - expect(call[2][1]).toMatchInlineSnapshot(` - ReactNativeFile { - "name": "filename-one.jpg", - "type": "image/jpeg", - "uri": "/path/to/file/filename-one.jpg", - } - `) - - // Second file - expect(call[3][0]).toBe("1") - expect(call[3][1]).toMatchInlineSnapshot(` - ReactNativeFile { - "name": "filename-two.jpg", - "type": "image/jpeg", - "uri": "/path/to/file/filename-two.jpg", - } - `) - }) - - it("should remove `Content-Type` header", () => { - middleware(mockNext)(request) - const call = mockNext.mock.calls[0][0] - - expect(call.fetchOpts.headers).toMatchInlineSnapshot(` - { - "User-Agent": "user-agent-value", - "X-TIMEZONE": "Europe/Berlin", - "X-USER-ID": "user-id", - } - `) - }) -}) diff --git a/src/app/system/relay/middlewares/uploadMiddleware.ts b/src/app/system/relay/middlewares/uploadMiddleware.ts deleted file mode 100644 index 5bc08f153da..00000000000 --- a/src/app/system/relay/middlewares/uploadMiddleware.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { extractFiles, ReactNativeFile } from "extract-files" -import { Middleware, RelayNetworkLayerRequestBatch } from "react-relay-network-modern/node8" - -const isReactNativeFile = (value: any): value is T => { - return value instanceof ReactNativeFile -} - -let queryMap: any - -/** - * Note: this request will fail if you are using React Native debugger with "Network Inspect" feature enabled - * Note: we must definitely specify `name` for file, otherwise Metaphysics will assume that the file is NOT being passed - * - * Upload middleware from `react-relay-network-modern` with ReactNativeFile support - * Original: https://github.com/relay-tools/react-relay-network-modern/blob/master/src/middlewares/upload.js - * - * If we try to pass Blob/File with specified `name` field to `fetch()`, we will get an error on Android. - * For this reason, support for these data formats is extracted from original `upload` middleware - * TODO: Add support for Blob/File when problem will be fixed for Android - */ -export const uploadMiddleware = (): Middleware => { - return (next) => async (req) => { - if (req instanceof RelayNetworkLayerRequestBatch) { - throw new Error("RelayRequestBatch is not supported") - } - - const { variables, id } = req - const result = extractFiles({ variables }, "", isReactNativeFile) - const { clone: extractedVariables, files } = result - - if (files.size) { - if (!queryMap) { - queryMap = require("../../../../../data/complete.queryMap.json") - } - - const query = queryMap[id] - const formData = new FormData() - const pathMap: Record = {} - let index = 0 - - for (const path of files.values()) { - pathMap[index++] = path - } - - formData.append("operations", JSON.stringify({ query, variables: extractedVariables })) - formData.append("map", JSON.stringify(pathMap)) - - index = 0 - for (const file of files.keys()) { - formData.append(String(index++), file) - } - - req.fetchOpts.method = "POST" - req.fetchOpts.body = formData - - delete req.fetchOpts.headers["Content-Type"] - } - - return await next(req) - } -} diff --git a/yarn.lock b/yarn.lock index 2e0e72f8cf8..394d0fa11ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4979,11 +4979,6 @@ resolved "https://registry.yarnpkg.com/@types/dedent/-/dedent-0.7.0.tgz#155f339ca404e6dd90b9ce46a3f78fd69ca9b050" integrity sha512-EGlKlgMhnLt/cM4DbUSafFdrkeJoC9Mvnj0PUCU7tFmTjMjNRT957kXCx0wYm3JuEq4o4ZsS5vG+NlkM2DMd2A== -"@types/extract-files@8.1.1": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@types/extract-files/-/extract-files-8.1.1.tgz#11b67e795ad2c8b483431e8d4f190db2fd22944b" - integrity sha512-dMJJqBqyhsfJKuK7p7HyyNmki7qj1AlwhUKWx6KrU7i1K2T2SPsUsSUTWFmr/sEM1q8rfR8j5IyUmYrDbrhfjQ== - "@types/geojson@*", "@types/geojson@^7946.0.7": version "7946.0.7" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad" @@ -8840,7 +8835,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-files@9.0.0, extract-files@^9.0.0: +extract-files@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==