From 832981b1d9c22cc7e55835aab393173aa82cf701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Costa=20Lima?= Date: Sun, 31 Jan 2021 19:33:34 +0000 Subject: [PATCH 01/18] feat: add React Native support --- .aegir.js | 2 +- .github/workflows/main.yml | 51 ++++++++++--- package.json | 10 ++- rn-test.config.js | 13 ++++ rn-test.require.js | 7 ++ src/env.js | 4 +- src/fetch.js | 6 +- src/http/fetch.js | 10 ++- src/http/fetch.react-native.js | 136 +++++++++++++++++++++++++++++++++ src/supports.js | 1 + test/env.spec.js | 44 +++++++++++ test/http.spec.js | 14 ++-- test/supports.spec.js | 24 ++++++ 13 files changed, 295 insertions(+), 27 deletions(-) create mode 100644 rn-test.config.js create mode 100644 rn-test.require.js create mode 100644 src/http/fetch.react-native.js diff --git a/.aegir.js b/.aegir.js index e0fddb4..91c53d4 100644 --- a/.aegir.js +++ b/.aegir.js @@ -42,4 +42,4 @@ module.exports = { await before.echoServer.stop() } } -} \ No newline at end of file +} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9e81b21..c67fb08 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,16 +11,16 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - run: npm install - - run: npx aegir lint - - uses: gozala/typescript-error-reporter-action@v1.0.8 - - run: npx aegir build - - run: npx aegir dep-check - - uses: ipfs/aegir/actions/bundle-size@master - name: size - with: - github_token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v2 + - run: npm install + - run: npx aegir lint + - uses: gozala/typescript-error-reporter-action@v1.0.8 + - run: npx aegir build + - run: npx aegir dep-check + - uses: ipfs/aegir/actions/bundle-size@master + name: size + with: + github_token: ${{ secrets.GITHUB_TOKEN }} test-node: needs: check runs-on: ${{ matrix.os }} @@ -64,4 +64,33 @@ jobs: steps: - uses: actions/checkout@v2 - run: npm install - - run: npx xvfb-maybe aegir test -t electron-renderer --bail \ No newline at end of file + - run: npx xvfb-maybe aegir test -t electron-renderer --bail + test-react-native-android: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - run: npm install + - uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 28 + target: default + arch: x86_64 + profile: pixel + avd-name: google-pixel + script: | + npx rn-test --platform android --emulator google-pixel 'test/**/*.spec.js' + test-react-native-ios: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - run: npm install + - name: Create and run iOS simulator + run: | + SIMULATOR_RUNTIME=$(echo "iOS 14.4" | sed 's/[ \.]/-/g') + SIMULATOR_ID=$(xcrun simctl create "iPhone 11" com.apple.CoreSimulator.SimDeviceType.iPhone-11 com.apple.CoreSimulator.SimRuntime.$SIMULATOR_RUNTIME) + echo "IOS_SIMULATOR=$SIMULATOR_ID" >> $GITHUB_ENV + xcrun simctl boot $SIMULATOR_ID & + - run: npx rn-test --platform ios --simulator 'iPhone 11 (14.4)' --rn 0.62.0 'test/**/*.spec.js' + - name: Shutdown iOS simulator + run: | + xcrun simctl shutdown $IOS_SIMULATOR diff --git a/package.json b/package.json index e35949e..5f5bd60 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,9 @@ "electron-fetch": false, "fs": false }, + "react-native": { + "./src/http/fetch.js": "./src/http/fetch.react-native.js" + }, "types": "dist/src/index.d.ts", "typesVersions": { "*": { @@ -36,6 +39,8 @@ "test:node": "aegir test -t node", "test:electron": "aegir test -t electron-main", "test:electron-renderer": "aegir test -t electron-renderer", + "test:react-native:android": "aegir test -t react-native-android", + "test:react-native:ios": "aegir test -t react-native-ios", "lint": "aegir lint", "release": "aegir release --docs", "release-minor": "aegir release --type minor --docs", @@ -50,7 +55,6 @@ "electron-fetch": "^1.7.2", "err-code": "^3.0.1", "is-electron": "^2.2.0", - "iso-url": "^1.0.0", "it-glob": "~0.0.11", "it-to-stream": "^1.0.0", "merge-options": "^3.0.4", @@ -58,6 +62,7 @@ "native-abort-controller": "^1.0.3", "native-fetch": "^3.0.0", "node-fetch": "^2.6.1", + "react-native-fetch-api": "^1.0.2", "stream-to-it": "^0.2.2" }, "devDependencies": { @@ -70,7 +75,8 @@ "it-last": "^1.0.4", "readable-stream": "^3.6.0", "uint8arrays": "^2.0.5", - "util": "^0.12.3" + "util": "^0.12.3", + "react-native-polyfill-globals": "^3.0.0" }, "eslintConfig": { "extends": "ipfs", diff --git a/rn-test.config.js b/rn-test.config.js new file mode 100644 index 0000000..fa050c3 --- /dev/null +++ b/rn-test.config.js @@ -0,0 +1,13 @@ +'use strict' + +module.exports = { + require: require.resolve('./rn-test.require.js'), + runner: 'mocha', + modules: [ + 'react-native-url-polyfill', + 'web-streams-polyfill' + ], + patches: [{ + path: require.resolve('react-native-polyfill-globals/patches/react-native+0.63.3.patch') + }] +} diff --git a/rn-test.require.js b/rn-test.require.js new file mode 100644 index 0000000..6462828 --- /dev/null +++ b/rn-test.require.js @@ -0,0 +1,7 @@ +'use strict' + +const { polyfill: polyfillReadableStream } = require('react-native-polyfill-globals/src/readable-stream') +const { polyfill: polyfillURL } = require('react-native-polyfill-globals/src/url') + +polyfillURL() +polyfillReadableStream() diff --git a/src/env.js b/src/env.js index eb1e826..15fd2ef 100644 --- a/src/env.js +++ b/src/env.js @@ -10,6 +10,7 @@ const IS_NODE = typeof require === 'function' && typeof process !== 'undefined' // @ts-ignore - we either ignore worker scope or dom scope const IS_WEBWORKER = typeof importScripts === 'function' && typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope const IS_TEST = typeof process !== 'undefined' && typeof process.env !== 'undefined' && process.env.NODE_ENV === 'test' +const IS_REACT_NATIVE = typeof navigator !== 'undefined' && navigator.product === 'ReactNative' module.exports = { isTest: IS_TEST, @@ -22,5 +23,6 @@ module.exports = { */ isBrowser: IS_BROWSER, isWebWorker: IS_WEBWORKER, - isEnvWithDom: IS_ENV_WITH_DOM + isEnvWithDom: IS_ENV_WITH_DOM, + isReactNative: IS_REACT_NATIVE } diff --git a/src/fetch.js b/src/fetch.js index d3ee792..ace949e 100644 --- a/src/fetch.js +++ b/src/fetch.js @@ -1,8 +1,10 @@ 'use strict' -const { isElectronMain } = require('./env') +const { isElectronMain, isReactNative } = require('./env') -if (isElectronMain) { +if (isReactNative) { + module.exports = require('react-native-fetch-api') +} else if (isElectronMain) { module.exports = require('electron-fetch') } else { // use window.fetch if it is available, fall back to node-fetch if not diff --git a/src/http/fetch.js b/src/http/fetch.js index 752cc2a..31d7ee4 100644 --- a/src/http/fetch.js +++ b/src/http/fetch.js @@ -1,8 +1,12 @@ 'use strict' -// Electron has `XMLHttpRequest` and should get the browser implementation -// instead of node. -if (typeof XMLHttpRequest === 'function') { +const { isReactNative } = require('../env') + +if (isReactNative) { + module.exports = require('./fetch.react-native') +} else if (typeof XMLHttpRequest === 'function') { + // Electron has `XMLHttpRequest` and should get the browser implementation + // instead of node. module.exports = require('./fetch.browser') } else { module.exports = require('./fetch.node') diff --git a/src/http/fetch.react-native.js b/src/http/fetch.react-native.js new file mode 100644 index 0000000..53ca0e1 --- /dev/null +++ b/src/http/fetch.react-native.js @@ -0,0 +1,136 @@ +'use strict' + +const { TimeoutError, AbortError } = require('./error') +const { Response, Request, Headers, fetch } = require('../fetch') + +/** + * @typedef {import('../types').FetchOptions} FetchOptions + * @typedef {import('../types').ProgressFn} ProgressFn + */ + +/** + * Fetch with progress + * + * @param {string | Request} url + * @param {FetchOptions} [options] + * @returns {Promise} + */ +const fetchWithProgress = (url, options = {}) => { + const request = new XMLHttpRequest() + request.open(options.method || 'GET', url.toString(), true) + + const { timeout, headers } = options + + if (timeout && timeout > 0 && timeout < Infinity) { + request.timeout = timeout + } + + if (options.overrideMimeType != null) { + request.overrideMimeType(options.overrideMimeType) + } + + if (headers) { + for (const [name, value] of new Headers(headers)) { + request.setRequestHeader(name, value) + } + } + + if (options.signal) { + options.signal.onabort = () => request.abort() + } + + if (options.onUploadProgress) { + request.upload.onprogress = options.onUploadProgress + } + + request.responseType = 'blob' + + return new Promise((resolve, reject) => { + /** + * @param {Event} event + */ + const handleEvent = (event) => { + switch (event.type) { + case 'error': { + resolve(Response.error()) + break + } + case 'load': { + resolve( + new ResponseWithURL(request.responseURL, request.response, { + status: request.status, + statusText: request.statusText, + headers: parseHeaders(request.getAllResponseHeaders()) + }) + ) + break + } + case 'timeout': { + reject(new TimeoutError()) + break + } + case 'abort': { + reject(new AbortError()) + break + } + default: { + break + } + } + } + request.onerror = handleEvent + request.onload = handleEvent + request.ontimeout = handleEvent + request.onabort = handleEvent + + request.send(/** @type {BodyInit} */(options.body)) + }) +} + +const fetchWithStreaming = fetch + +/** + * @param {string | Request} url + * @param {FetchOptions} options + */ +const fetchWith = (url, options = {}) => + (options.onUploadProgress != null) + ? fetchWithProgress(url, options) + : fetchWithStreaming(url, options) + +/** + * Parse Headers from a XMLHttpRequest + * + * @param {string} input + * @returns {Headers} + */ +const parseHeaders = (input) => { + const headers = new Headers() + for (const line of input.trim().split(/[\r\n]+/)) { + const index = line.indexOf(': ') + if (index > 0) { + headers.set(line.slice(0, index), line.slice(index + 1)) + } + } + + return headers +} + +class ResponseWithURL extends Response { + /** + * @param {string} url + * @param {BodyInit} body + * @param {ResponseInit} options + */ + constructor (url, body, options) { + super(body, options) + Object.defineProperty(this, 'url', { value: url }) + } +} + +module.exports = { + fetch: fetchWith, + Request, + Headers, + ResponseWithURL +} diff --git a/src/supports.js b/src/supports.js index f66f9bd..cadc86f 100644 --- a/src/supports.js +++ b/src/supports.js @@ -1,6 +1,7 @@ 'use strict' module.exports = { + // in React Native: global === window === self supportsFileReader: typeof self !== 'undefined' && 'FileReader' in self, supportsWebRTC: 'RTCPeerConnection' in globalThis && (typeof navigator !== 'undefined' && typeof navigator.mediaDevices !== 'undefined' && 'getUserMedia' in navigator.mediaDevices), diff --git a/test/env.spec.js b/test/env.spec.js index 910783d..359bfee 100644 --- a/test/env.spec.js +++ b/test/env.spec.js @@ -22,6 +22,9 @@ describe('env', function () { case 'webworker': expect(env.isElectron).to.be.false() break + case 'react-native': + expect(env.isElectron).to.be.false() + break default: expect.fail(`Could not detect env. Current env is ${process.env.AEGIR_RUNNER}`) break @@ -45,6 +48,9 @@ describe('env', function () { case 'webworker': expect(env.isElectronMain).to.be.false() break + case 'react-native': + expect(env.isElectronMain).to.be.false() + break default: expect.fail(`Could not detect env. Current env is ${process.env.AEGIR_RUNNER}`) break @@ -68,6 +74,9 @@ describe('env', function () { case 'webworker': expect(env.isElectronRenderer).to.be.false() break + case 'react-native': + expect(env.isElectronRenderer).to.be.false() + break default: expect.fail(`Could not detect env. Current env is ${process.env.AEGIR_RUNNER}`) break @@ -91,6 +100,9 @@ describe('env', function () { case 'webworker': expect(env.isNode).to.be.false() break + case 'react-native': + expect(env.isNode).to.be.false() + break default: expect.fail(`Could not detect env. Current env is ${process.env.AEGIR_RUNNER}`) break @@ -114,6 +126,9 @@ describe('env', function () { case 'webworker': expect(env.isBrowser).to.be.false() break + case 'react-native': + expect(env.isBrowser).to.be.false() + break default: expect.fail(`Could not detect env. Current env is ${process.env.AEGIR_RUNNER}`) break @@ -137,6 +152,35 @@ describe('env', function () { case 'webworker': expect(env.isWebWorker).to.be.true() break + case 'react-native': + expect(env.isWebWorker).to.be.false() + break + default: + expect.fail(`Could not detect env. Current env is ${process.env.AEGIR_RUNNER}`) + break + } + }) + + it('isReactNative should have the correct value in each env', function () { + switch (process.env.AEGIR_RUNNER) { + case 'electron-main': + expect(env.isReactNative).to.be.false() + break + case 'electron-renderer': + expect(env.isReactNative).to.be.false() + break + case 'node': + expect(env.isReactNative).to.be.false() + break + case 'browser': + expect(env.isReactNative).to.be.false() + break + case 'webworker': + expect(env.isReactNative).to.be.false() + break + case 'react-native': + expect(env.isReactNative).to.be.true() + break default: expect.fail(`Could not detect env. Current env is ${process.env.AEGIR_RUNNER}`) break diff --git a/test/http.spec.js b/test/http.spec.js index 0d6f3bd..058a7a8 100644 --- a/test/http.spec.js +++ b/test/http.spec.js @@ -9,7 +9,7 @@ const delay = require('delay') const { AbortController } = require('native-abort-controller') const drain = require('it-drain') const all = require('it-all') -const { isBrowser, isWebWorker } = require('../src/env') +const { isBrowser, isWebWorker, isReactNative } = require('../src/env') const { Buffer } = require('buffer') const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayEquals = require('uint8arrays/equals') @@ -86,7 +86,7 @@ describe('http', function () { }) controller.abort() - await expect(res).to.eventually.be.rejectedWith(/aborted/) + await expect(res).to.eventually.be.rejectedWith(/aborted/i) }) it('parses the response as ndjson', async function () { @@ -111,8 +111,8 @@ describe('http', function () { }) it.skip('should handle errors in streaming bodies', async function () { - if (isBrowser || isWebWorker) { - // streaming bodies not supported by browsers + if (isBrowser || isWebWorker || isReactNative) { + // streaming bodies not supported by browsers nor by React Native return this.skip() } @@ -133,8 +133,8 @@ describe('http', function () { }) it.skip('should handle errors in streaming bodies when a signal is passed', async function () { - if (isBrowser || isWebWorker) { - // streaming bodies not supported by browsers + if (isBrowser || isWebWorker || isReactNative) { + // streaming bodies not supported by browsers nor by React Native return this.skip() } @@ -155,7 +155,7 @@ describe('http', function () { await expect(drain(res.ndjson())).to.eventually.be.rejectedWith(/aborted/) }) - it('progress events', async () => { + it('progress events', async function () { let upload = 0 const body = new Uint8Array(1000000 / 2) const request = await HTTP.post(`${ECHO_SERVER}/echo`, { diff --git a/test/supports.spec.js b/test/supports.spec.js index c4e11b4..b0070a8 100644 --- a/test/supports.spec.js +++ b/test/supports.spec.js @@ -46,6 +46,14 @@ describe('supports', function () { } }) + it('supportsFileReader should return true in React Native', function () { + if (env.isReactNative) { + expect(supports.supportsFileReader).to.be.true() + } else { + this.skip() + } + }) + it('supportsWebRTC should return false in node', function () { if (env.isNode) { expect(supports.supportsWebRTC).to.be.false() @@ -86,6 +94,14 @@ describe('supports', function () { } }) + it('supportsWebRTC should return false in React Native', function () { + if (env.isReactNative) { + expect(supports.supportsWebRTC).to.be.false() + } else { + this.skip() + } + }) + it('supportsWebRTCDataChannels should return false in node', function () { if (env.isNode) { expect(supports.supportsWebRTCDataChannels).to.be.false() @@ -125,4 +141,12 @@ describe('supports', function () { this.skip() } }) + + it('supportsWebRTCDataChannels should return true in React Native', function () { + if (env.isReactNative) { + expect(supports.supportsWebRTCDataChannels).to.be.false() + } else { + this.skip() + } + }) }) From 32e5be059c3995591aadb879026411dc858ea0a8 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 25 Mar 2021 17:18:17 +0000 Subject: [PATCH 02/18] fix: fix fetch types --- package.json | 3 ++- src/env.js | 1 + src/fetch.js | 6 ++---- src/fetch.rn.js | 18 ++++++++++++++++++ src/http.js | 3 +-- src/http/fetch.js | 6 +----- src/http/fetch.node.js | 4 +--- .../{fetch.react-native.js => fetch.rn.js} | 3 ++- src/types.d.ts | 1 + tsconfig.json | 16 ++++++++++------ 10 files changed, 39 insertions(+), 22 deletions(-) create mode 100644 src/fetch.rn.js rename src/http/{fetch.react-native.js => fetch.rn.js} (97%) diff --git a/package.json b/package.json index 5f5bd60..cf4742c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "fs": false }, "react-native": { - "./src/http/fetch.js": "./src/http/fetch.react-native.js" + "./src/fetch.js": "./src/fetch.rn.js", + "./src/http/fetch.js": "./src/http/fetch.rn.js" }, "types": "dist/src/index.d.ts", "typesVersions": { diff --git a/src/env.js b/src/env.js index 15fd2ef..c89a1b0 100644 --- a/src/env.js +++ b/src/env.js @@ -2,6 +2,7 @@ const isElectron = require('is-electron') const IS_ENV_WITH_DOM = typeof window === 'object' && typeof document === 'object' && document.nodeType === 9 +// @ts-ignore const IS_ELECTRON = isElectron() const IS_BROWSER = IS_ENV_WITH_DOM && !IS_ELECTRON const IS_ELECTRON_MAIN = IS_ELECTRON && !IS_ENV_WITH_DOM diff --git a/src/fetch.js b/src/fetch.js index ace949e..d3ee792 100644 --- a/src/fetch.js +++ b/src/fetch.js @@ -1,10 +1,8 @@ 'use strict' -const { isElectronMain, isReactNative } = require('./env') +const { isElectronMain } = require('./env') -if (isReactNative) { - module.exports = require('react-native-fetch-api') -} else if (isElectronMain) { +if (isElectronMain) { module.exports = require('electron-fetch') } else { // use window.fetch if it is available, fall back to node-fetch if not diff --git a/src/fetch.rn.js b/src/fetch.rn.js new file mode 100644 index 0000000..54688ed --- /dev/null +++ b/src/fetch.rn.js @@ -0,0 +1,18 @@ +// @ts-nocheck +'use strict' +// @ts-ignore +const { Headers, Request, Response, fetch } = require('react-native-fetch-api') + +/** @type {import('electron-fetch').default} */ +const rnFetch = fetch +/** @type {import('electron-fetch').Headers} */ +const rnHeaders = Headers +/** @type {import('electron-fetch').Request} */ +const rnRequest = Request +/** @type {import('electron-fetch').Response} */ +const rnResponse = Response +module.exports = rnFetch +module.exports.Headers = rnHeaders +module.exports.Request = rnRequest +module.exports.Response = rnResponse +module.exports.default = rnFetch diff --git a/src/http.js b/src/http.js index ba88fdf..9ce142c 100644 --- a/src/http.js +++ b/src/http.js @@ -9,10 +9,9 @@ const { AbortController } = require('native-abort-controller') const anySignal = require('any-signal') /** - * @typedef {import('./types').ExtendedResponse} ExtendedResponse * @typedef {import('stream').Readable} NodeReadableStream - * @typedef {import('stream').Duplex} NodeDuplexStream * @typedef {import('./types').HTTPOptions} HTTPOptions + * @typedef {import('./types').ExtendedResponse} ExtendedResponse */ /** diff --git a/src/http/fetch.js b/src/http/fetch.js index 31d7ee4..3746641 100644 --- a/src/http/fetch.js +++ b/src/http/fetch.js @@ -1,10 +1,6 @@ 'use strict' -const { isReactNative } = require('../env') - -if (isReactNative) { - module.exports = require('./fetch.react-native') -} else if (typeof XMLHttpRequest === 'function') { +if (typeof XMLHttpRequest === 'function') { // Electron has `XMLHttpRequest` and should get the browser implementation // instead of node. module.exports = require('./fetch.browser') diff --git a/src/http/fetch.node.js b/src/http/fetch.node.js index ae0ed0f..32b9d59 100644 --- a/src/http/fetch.node.js +++ b/src/http/fetch.node.js @@ -1,5 +1,4 @@ 'use strict' - const { Request, Response, Headers, default: nativeFetch } = require('../fetch') // @ts-ignore const toStream = require('it-to-stream') @@ -46,8 +45,7 @@ const withUploadProgress = (options) => { } /** - * @param {BodyInit} input - * @returns {Blob | FormData | URLSearchParams | ReadableStream | string | NodeReadableStream | Buffer} + * @param {BodyInit | NodeReadableStream} input */ const normalizeBody = (input) => { if (input instanceof ArrayBuffer) { diff --git a/src/http/fetch.react-native.js b/src/http/fetch.rn.js similarity index 97% rename from src/http/fetch.react-native.js rename to src/http/fetch.rn.js index 53ca0e1..da7735c 100644 --- a/src/http/fetch.react-native.js +++ b/src/http/fetch.rn.js @@ -1,7 +1,8 @@ +// @ts-nocheck 'use strict' const { TimeoutError, AbortError } = require('./error') -const { Response, Request, Headers, fetch } = require('../fetch') +const { Response, Request, Headers, default: fetch } = require('../fetch') /** * @typedef {import('../types').FetchOptions} FetchOptions diff --git a/src/types.d.ts b/src/types.d.ts index 2ee6223..534de28 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -7,6 +7,7 @@ interface ProgressStatus { export interface ProgressFn { (status: ProgressStatus): void } export interface FetchOptions extends RequestInit { + body?: BodyInit | null | NodeReadableStream /** * Amount of time until request should timeout in ms. */ diff --git a/tsconfig.json b/tsconfig.json index b008382..466f765 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,15 @@ { "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { - "outDir": "dist", - "baseUrl": "./", - "paths": { - "*": ["./types/*"] - } + "outDir": "dist" + // "baseUrl": "./", + // "paths": { + // "*": ["./types/*"] + // } }, - "include": ["types", "test", "src"] + "include": [ + // "types", + "test", + "src" + ] } From fe20bdee9b8d9182c48766d55eea098b46cb331d Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 7 Apr 2021 17:04:50 +0100 Subject: [PATCH 03/18] fix: code tweaks for rn --- test/http.spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/http.spec.js b/test/http.spec.js index 058a7a8..2dbf4d5 100644 --- a/test/http.spec.js +++ b/test/http.spec.js @@ -160,6 +160,9 @@ describe('http', function () { const body = new Uint8Array(1000000 / 2) const request = await HTTP.post(`${ECHO_SERVER}/echo`, { body, + headers: { + 'Content-Type': 'application/octet-stream' + }, onUploadProgress: (progress) => { expect(progress).to.have.property('lengthComputable').to.be.a('boolean') expect(progress).to.have.property('total', body.byteLength) From d654c9d7a959ef3e09ba316ecbfebbcc9f4dc2cf Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 7 Apr 2021 17:07:06 +0100 Subject: [PATCH 04/18] fix: revert .aegir and update deps --- .aegir.js | 2 +- src/types.d.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.aegir.js b/.aegir.js index 91c53d4..6b41839 100644 --- a/.aegir.js +++ b/.aegir.js @@ -1,4 +1,4 @@ -'use strict' +'use strict'; const EchoServer = require('aegir/utils/echo-server') const { format } =require('iso-url') diff --git a/src/types.d.ts b/src/types.d.ts index 534de28..b805e09 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -7,6 +7,9 @@ interface ProgressStatus { export interface ProgressFn { (status: ProgressStatus): void } export interface FetchOptions extends RequestInit { + /** + * Extended body with support for node readable stream + */ body?: BodyInit | null | NodeReadableStream /** * Amount of time until request should timeout in ms. From 3be3643b4dae9711459c5c28590d80dff768dd64 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Wed, 7 Apr 2021 17:23:37 +0100 Subject: [PATCH 05/18] fix: fix test for rn --- test/env.spec.js | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/test/env.spec.js b/test/env.spec.js index 359bfee..13d5352 100644 --- a/test/env.spec.js +++ b/test/env.spec.js @@ -22,7 +22,10 @@ describe('env', function () { case 'webworker': expect(env.isElectron).to.be.false() break - case 'react-native': + case 'react-native-android': + expect(env.isElectron).to.be.false() + break + case 'react-native-ios': expect(env.isElectron).to.be.false() break default: @@ -48,7 +51,10 @@ describe('env', function () { case 'webworker': expect(env.isElectronMain).to.be.false() break - case 'react-native': + case 'react-native-android': + expect(env.isElectronMain).to.be.false() + break + case 'react-native-ios': expect(env.isElectronMain).to.be.false() break default: @@ -74,7 +80,10 @@ describe('env', function () { case 'webworker': expect(env.isElectronRenderer).to.be.false() break - case 'react-native': + case 'react-native-android': + expect(env.isElectronRenderer).to.be.false() + break + case 'react-native-ios': expect(env.isElectronRenderer).to.be.false() break default: @@ -100,7 +109,10 @@ describe('env', function () { case 'webworker': expect(env.isNode).to.be.false() break - case 'react-native': + case 'react-native-android': + expect(env.isNode).to.be.false() + break + case 'react-native-ios': expect(env.isNode).to.be.false() break default: @@ -126,7 +138,10 @@ describe('env', function () { case 'webworker': expect(env.isBrowser).to.be.false() break - case 'react-native': + case 'react-native-android': + expect(env.isBrowser).to.be.false() + break + case 'react-native-ios': expect(env.isBrowser).to.be.false() break default: @@ -152,7 +167,10 @@ describe('env', function () { case 'webworker': expect(env.isWebWorker).to.be.true() break - case 'react-native': + case 'react-native-android': + expect(env.isWebWorker).to.be.false() + break + case 'react-native-ios': expect(env.isWebWorker).to.be.false() break default: @@ -178,7 +196,10 @@ describe('env', function () { case 'webworker': expect(env.isReactNative).to.be.false() break - case 'react-native': + case 'react-native-android': + expect(env.isReactNative).to.be.true() + break + case 'react-native-ios': expect(env.isReactNative).to.be.true() break default: From 9aa1ee0b7be456ae9f6025507555eb96ba23e1cc Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 15:31:39 +0100 Subject: [PATCH 06/18] fix: add aegir --- .aegir.js | 11 +++++++---- .github/workflows/main.yml | 34 +++++++++++++++++----------------- package.json | 6 +++--- tsconfig.json | 5 ----- types/is-electron/index.d.ts | 2 -- 5 files changed, 27 insertions(+), 31 deletions(-) delete mode 100644 types/is-electron/index.d.ts diff --git a/.aegir.js b/.aegir.js index 6b41839..ccabddb 100644 --- a/.aegir.js +++ b/.aegir.js @@ -2,11 +2,9 @@ const EchoServer = require('aegir/utils/echo-server') const { format } =require('iso-url') -const path = require('path') /** @type {import('aegir').Options["build"]["config"]} */ const esbuild = { - //inject: [path.join(__dirname, '../../scripts/node-globals.js')], plugins: [ { name: 'node built ins', @@ -19,6 +17,7 @@ const esbuild = { ] } +/** @type {import('aegir').PartialOptions} */ module.exports = { build: { config: esbuild @@ -29,13 +28,17 @@ module.exports = { buildConfig: esbuild } }, - before: async () => { + async before (options) { let echoServer = new EchoServer() await echoServer.start() const { address, port } = echoServer.server.address() + let hostname = address + if(options.runner === 'react-native-android') { + hostname = '10.0.2.2' + } return { echoServer, - env: { ECHO_SERVER : format({ protocol: 'http:', hostname: address, port })} + env: { ECHO_SERVER : format({ protocol: 'http:', hostname, port })} } }, async after (options, before) { diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c67fb08..f772741 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -76,21 +76,21 @@ jobs: target: default arch: x86_64 profile: pixel - avd-name: google-pixel + avd-name: aegir-android-29 script: | - npx rn-test --platform android --emulator google-pixel 'test/**/*.spec.js' - test-react-native-ios: - runs-on: macos-latest - steps: - - uses: actions/checkout@v2 - - run: npm install - - name: Create and run iOS simulator - run: | - SIMULATOR_RUNTIME=$(echo "iOS 14.4" | sed 's/[ \.]/-/g') - SIMULATOR_ID=$(xcrun simctl create "iPhone 11" com.apple.CoreSimulator.SimDeviceType.iPhone-11 com.apple.CoreSimulator.SimRuntime.$SIMULATOR_RUNTIME) - echo "IOS_SIMULATOR=$SIMULATOR_ID" >> $GITHUB_ENV - xcrun simctl boot $SIMULATOR_ID & - - run: npx rn-test --platform ios --simulator 'iPhone 11 (14.4)' --rn 0.62.0 'test/**/*.spec.js' - - name: Shutdown iOS simulator - run: | - xcrun simctl shutdown $IOS_SIMULATOR + npx aegir test -t react-native-android' + # test-react-native-ios: + # runs-on: macos-latest + # steps: + # - uses: actions/checkout@v2 + # - run: npm install + # - name: Create and run iOS simulator + # run: | + # SIMULATOR_RUNTIME=$(echo "iOS 14.4" | sed 's/[ \.]/-/g') + # SIMULATOR_ID=$(xcrun simctl create "iPhone 11" com.apple.CoreSimulator.SimDeviceType.iPhone-11 com.apple.CoreSimulator.SimRuntime.$SIMULATOR_RUNTIME) + # echo "IOS_SIMULATOR=$SIMULATOR_ID" >> $GITHUB_ENV + # xcrun simctl boot $SIMULATOR_ID & + # - run: npx rn-test --platform ios --simulator 'iPhone 11 (14.4)' --rn 0.62.0 'test/**/*.spec.js' + # - name: Shutdown iOS simulator + # run: | + # xcrun simctl shutdown $IOS_SIMULATOR diff --git a/package.json b/package.json index cf4742c..7f47036 100644 --- a/package.json +++ b/package.json @@ -67,17 +67,17 @@ "stream-to-it": "^0.2.2" }, "devDependencies": { - "aegir": "^33.1.0", + "aegir": "ipfs/aegir#feat/rn", "delay": "^5.0.0", "events": "^3.3.0", "ipfs-unixfs": "^4.0.1", "it-all": "^1.0.4", "it-drain": "^1.0.3", "it-last": "^1.0.4", + "react-native-polyfill-globals": "^3.0.0", "readable-stream": "^3.6.0", "uint8arrays": "^2.0.5", - "util": "^0.12.3", - "react-native-polyfill-globals": "^3.0.0" + "util": "^0.12.3" }, "eslintConfig": { "extends": "ipfs", diff --git a/tsconfig.json b/tsconfig.json index 466f765..e882384 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,13 +2,8 @@ "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist" - // "baseUrl": "./", - // "paths": { - // "*": ["./types/*"] - // } }, "include": [ - // "types", "test", "src" ] diff --git a/types/is-electron/index.d.ts b/types/is-electron/index.d.ts deleted file mode 100644 index 0f33e26..0000000 --- a/types/is-electron/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -function isElectron (): boolean -export = isElectron From 157450ada8038045fad19f9edc0fe210dd796ecf Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 15:34:16 +0100 Subject: [PATCH 07/18] chore: fix ci --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f772741..df4d06f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -67,12 +67,13 @@ jobs: - run: npx xvfb-maybe aegir test -t electron-renderer --bail test-react-native-android: runs-on: macos-latest + needs: check steps: - uses: actions/checkout@v2 - run: npm install - uses: reactivecircus/android-emulator-runner@v2 with: - api-level: 28 + api-level: 29 target: default arch: x86_64 profile: pixel From 279a34810de82c3fba7bf5bd7cbe298c81c05e4a Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 15:43:17 +0100 Subject: [PATCH 08/18] chore: change android ci --- .github/workflows/main.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index df4d06f..2c200d4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -66,20 +66,21 @@ jobs: - run: npm install - run: npx xvfb-maybe aegir test -t electron-renderer --bail test-react-native-android: - runs-on: macos-latest + runs-on: ubuntu-latest needs: check steps: - uses: actions/checkout@v2 - run: npm install - - uses: reactivecircus/android-emulator-runner@v2 - with: - api-level: 29 - target: default - arch: x86_64 - profile: pixel - avd-name: aegir-android-29 - script: | - npx aegir test -t react-native-android' + - run: npx aegir test -t react-native-android + # - uses: reactivecircus/android-emulator-runner@v2 + # with: + # api-level: 29 + # target: default + # arch: x86_64 + # profile: pixel + # avd-name: aegir-android-29 + # script: | + # npx aegir test -t react-native-android' # test-react-native-ios: # runs-on: macos-latest # steps: From 3c52fd9fac14b0f7a03cb93300750aa61eda8ce2 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 15:50:09 +0100 Subject: [PATCH 09/18] chore: install emulator --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2c200d4..4fcdce5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -71,6 +71,7 @@ jobs: steps: - uses: actions/checkout@v2 - run: npm install + - run: sdkmanager --update && sdkmanager "emulator" - run: npx aegir test -t react-native-android # - uses: reactivecircus/android-emulator-runner@v2 # with: From 6115cc583f82335fb7a148bb9ea16d5422e18da4 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 16:04:56 +0100 Subject: [PATCH 10/18] chore: change to macos --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4fcdce5..88275b4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -66,7 +66,7 @@ jobs: - run: npm install - run: npx xvfb-maybe aegir test -t electron-renderer --bail test-react-native-android: - runs-on: ubuntu-latest + runs-on: macos-latest needs: check steps: - uses: actions/checkout@v2 From aeaf4b861d161b7048915b7e1616140798450f13 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 16:10:41 +0100 Subject: [PATCH 11/18] chore: change to macos remove sdkmanager --- .github/workflows/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 88275b4..5c82a26 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -71,7 +71,6 @@ jobs: steps: - uses: actions/checkout@v2 - run: npm install - - run: sdkmanager --update && sdkmanager "emulator" - run: npx aegir test -t react-native-android # - uses: reactivecircus/android-emulator-runner@v2 # with: From fe58ebbc18f3541a89d64cb044d7af0b3a4df145 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 16:25:53 +0100 Subject: [PATCH 12/18] chore: revert to action --- .github/workflows/main.yml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5c82a26..df4d06f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -71,16 +71,15 @@ jobs: steps: - uses: actions/checkout@v2 - run: npm install - - run: npx aegir test -t react-native-android - # - uses: reactivecircus/android-emulator-runner@v2 - # with: - # api-level: 29 - # target: default - # arch: x86_64 - # profile: pixel - # avd-name: aegir-android-29 - # script: | - # npx aegir test -t react-native-android' + - uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 29 + target: default + arch: x86_64 + profile: pixel + avd-name: aegir-android-29 + script: | + npx aegir test -t react-native-android' # test-react-native-ios: # runs-on: macos-latest # steps: From 5a283f7df6620a842b1d3863c02ea1a8bd61dd62 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 16:36:49 +0100 Subject: [PATCH 13/18] chore: revert to action type --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index df4d06f..dbcacf4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,7 +79,7 @@ jobs: profile: pixel avd-name: aegir-android-29 script: | - npx aegir test -t react-native-android' + npx aegir test -t react-native-android # test-react-native-ios: # runs-on: macos-latest # steps: From 5b4b1e6d25446e054e4d84f5a08102ae88e9457b Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 17:13:54 +0100 Subject: [PATCH 14/18] chore: ci env var --- .github/workflows/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dbcacf4..b931a89 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,7 @@ name: ci +env: + CI: true + FORCE_COLOR: 1 on: push: branches: From 5c5c782617769c4c10bd796585038e69f0b95300 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 18:02:54 +0100 Subject: [PATCH 15/18] fix: add encoding polyfil --- rn-test.config.js | 3 ++- rn-test.require.js | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/rn-test.config.js b/rn-test.config.js index fa050c3..6e94e80 100644 --- a/rn-test.config.js +++ b/rn-test.config.js @@ -5,7 +5,8 @@ module.exports = { runner: 'mocha', modules: [ 'react-native-url-polyfill', - 'web-streams-polyfill' + 'web-streams-polyfill', + 'text-encoding' ], patches: [{ path: require.resolve('react-native-polyfill-globals/patches/react-native+0.63.3.patch') diff --git a/rn-test.require.js b/rn-test.require.js index 6462828..9a37889 100644 --- a/rn-test.require.js +++ b/rn-test.require.js @@ -2,6 +2,8 @@ const { polyfill: polyfillReadableStream } = require('react-native-polyfill-globals/src/readable-stream') const { polyfill: polyfillURL } = require('react-native-polyfill-globals/src/url') +const { polyfill: polyfillEncoding } = require('react-native-polyfill-globals/src/encoding') polyfillURL() polyfillReadableStream() +polyfillEncoding() From c4ce4cecdfc3d93550a11c32d14932d0fbbd4697 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Thu, 8 Apr 2021 18:22:13 +0100 Subject: [PATCH 16/18] chore: increase timeout --- test/http.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/http.spec.js b/test/http.spec.js index 2dbf4d5..7e48c1f 100644 --- a/test/http.spec.js +++ b/test/http.spec.js @@ -156,6 +156,7 @@ describe('http', function () { }) it('progress events', async function () { + this.timeout(10000) let upload = 0 const body = new Uint8Array(1000000 / 2) const request = await HTTP.post(`${ECHO_SERVER}/echo`, { From 2b60a7f725cb83244afa492ace994f2926241731 Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Fri, 21 May 2021 12:58:17 +0100 Subject: [PATCH 17/18] chore: add iso-url --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 7f47036..6a0d06a 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "electron-fetch": "^1.7.2", "err-code": "^3.0.1", "is-electron": "^2.2.0", + "iso-url": "^1.1.5", "it-glob": "~0.0.11", "it-to-stream": "^1.0.0", "merge-options": "^3.0.4", From d7f29262a127356099a86fdb624f88dc3570467a Mon Sep 17 00:00:00 2001 From: Hugo Dias Date: Fri, 21 May 2021 15:19:24 +0100 Subject: [PATCH 18/18] chore: update aegir --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a0d06a..e0d069e 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "stream-to-it": "^0.2.2" }, "devDependencies": { - "aegir": "ipfs/aegir#feat/rn", + "aegir": "^33.2.0", "delay": "^5.0.0", "events": "^3.3.0", "ipfs-unixfs": "^4.0.1",