Skip to content

Commit

Permalink
feat: add React Native android support (#91)
Browse files Browse the repository at this point in the history
Co-authored-by: Hugo Dias <hugomrdias@gmail.com>
  • Loading branch information
acostalima and hugomrdias authored May 21, 2021
1 parent c00c353 commit b2b02a5
Show file tree
Hide file tree
Showing 18 changed files with 359 additions and 42 deletions.
15 changes: 9 additions & 6 deletions .aegir.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
'use strict'
'use strict';

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',
Expand All @@ -19,6 +17,7 @@ const esbuild = {
]
}

/** @type {import('aegir').PartialOptions} */
module.exports = {
build: {
config: esbuild
Expand All @@ -29,17 +28,21 @@ 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) {
await before.echoServer.stop()
}
}
}
}
55 changes: 44 additions & 11 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
name: ci
env:
CI: true
FORCE_COLOR: 1
on:
push:
branches:
Expand All @@ -11,16 +14,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 }}
Expand Down Expand Up @@ -64,4 +67,34 @@ jobs:
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npx xvfb-maybe aegir test -t electron-renderer --bail
- 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: 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:
# - 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
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
"electron-fetch": false,
"fs": false
},
"react-native": {
"./src/fetch.js": "./src/fetch.rn.js",
"./src/http/fetch.js": "./src/http/fetch.rn.js"
},
"types": "dist/src/index.d.ts",
"typesVersions": {
"*": {
Expand All @@ -36,6 +40,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",
Expand All @@ -50,24 +56,26 @@
"electron-fetch": "^1.7.2",
"err-code": "^3.0.1",
"is-electron": "^2.2.0",
"iso-url": "^1.0.0",
"iso-url": "^1.1.5",
"it-glob": "~0.0.11",
"it-to-stream": "^1.0.0",
"merge-options": "^3.0.4",
"nanoid": "^3.1.20",
"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": {
"aegir": "^33.1.0",
"aegir": "^33.2.0",
"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"
Expand Down
14 changes: 14 additions & 0 deletions rn-test.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict'

module.exports = {
require: require.resolve('./rn-test.require.js'),
runner: 'mocha',
modules: [
'react-native-url-polyfill',
'web-streams-polyfill',
'text-encoding'
],
patches: [{
path: require.resolve('react-native-polyfill-globals/patches/react-native+0.63.3.patch')
}]
}
9 changes: 9 additions & 0 deletions rn-test.require.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict'

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()
5 changes: 4 additions & 1 deletion src/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -10,6 +11,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,
Expand All @@ -22,5 +24,6 @@ module.exports = {
*/
isBrowser: IS_BROWSER,
isWebWorker: IS_WEBWORKER,
isEnvWithDom: IS_ENV_WITH_DOM
isEnvWithDom: IS_ENV_WITH_DOM,
isReactNative: IS_REACT_NATIVE
}
18 changes: 18 additions & 0 deletions src/fetch.rn.js
Original file line number Diff line number Diff line change
@@ -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
3 changes: 1 addition & 2 deletions src/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/

/**
Expand Down
4 changes: 2 additions & 2 deletions src/http/fetch.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use strict'

// Electron has `XMLHttpRequest` and should get the browser implementation
// instead of node.
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')
Expand Down
4 changes: 1 addition & 3 deletions src/http/fetch.node.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
'use strict'

const { Request, Response, Headers, default: nativeFetch } = require('../fetch')
// @ts-ignore
const toStream = require('it-to-stream')
Expand Down Expand Up @@ -46,8 +45,7 @@ const withUploadProgress = (options) => {
}

/**
* @param {BodyInit} input
* @returns {Blob | FormData | URLSearchParams | ReadableStream<Uint8Array> | string | NodeReadableStream | Buffer}
* @param {BodyInit | NodeReadableStream} input
*/
const normalizeBody = (input) => {
if (input instanceof ArrayBuffer) {
Expand Down
Loading

0 comments on commit b2b02a5

Please sign in to comment.