Skip to content

Commit b2b02a5

Browse files
feat: add React Native android support (#91)
Co-authored-by: Hugo Dias <[email protected]>
1 parent c00c353 commit b2b02a5

18 files changed

+359
-42
lines changed

.aegir.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
'use strict'
1+
'use strict';
22

33
const EchoServer = require('aegir/utils/echo-server')
44
const { format } =require('iso-url')
5-
const path = require('path')
65

76
/** @type {import('aegir').Options["build"]["config"]} */
87
const esbuild = {
9-
//inject: [path.join(__dirname, '../../scripts/node-globals.js')],
108
plugins: [
119
{
1210
name: 'node built ins',
@@ -19,6 +17,7 @@ const esbuild = {
1917
]
2018
}
2119

20+
/** @type {import('aegir').PartialOptions} */
2221
module.exports = {
2322
build: {
2423
config: esbuild
@@ -29,17 +28,21 @@ module.exports = {
2928
buildConfig: esbuild
3029
}
3130
},
32-
before: async () => {
31+
async before (options) {
3332
let echoServer = new EchoServer()
3433
await echoServer.start()
3534
const { address, port } = echoServer.server.address()
35+
let hostname = address
36+
if(options.runner === 'react-native-android') {
37+
hostname = '10.0.2.2'
38+
}
3639
return {
3740
echoServer,
38-
env: { ECHO_SERVER : format({ protocol: 'http:', hostname: address, port })}
41+
env: { ECHO_SERVER : format({ protocol: 'http:', hostname, port })}
3942
}
4043
},
4144
async after (options, before) {
4245
await before.echoServer.stop()
4346
}
4447
}
45-
}
48+
}

.github/workflows/main.yml

+44-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
name: ci
2+
env:
3+
CI: true
4+
FORCE_COLOR: 1
25
on:
36
push:
47
branches:
@@ -11,16 +14,16 @@ jobs:
1114
check:
1215
runs-on: ubuntu-latest
1316
steps:
14-
- uses: actions/checkout@v2
15-
- run: npm install
16-
- run: npx aegir lint
17-
- uses: gozala/[email protected]
18-
- run: npx aegir build
19-
- run: npx aegir dep-check
20-
- uses: ipfs/aegir/actions/bundle-size@master
21-
name: size
22-
with:
23-
github_token: ${{ secrets.GITHUB_TOKEN }}
17+
- uses: actions/checkout@v2
18+
- run: npm install
19+
- run: npx aegir lint
20+
- uses: gozala/[email protected]
21+
- run: npx aegir build
22+
- run: npx aegir dep-check
23+
- uses: ipfs/aegir/actions/bundle-size@master
24+
name: size
25+
with:
26+
github_token: ${{ secrets.GITHUB_TOKEN }}
2427
test-node:
2528
needs: check
2629
runs-on: ${{ matrix.os }}
@@ -64,4 +67,34 @@ jobs:
6467
steps:
6568
- uses: actions/checkout@v2
6669
- run: npm install
67-
- run: npx xvfb-maybe aegir test -t electron-renderer --bail
70+
- run: npx xvfb-maybe aegir test -t electron-renderer --bail
71+
test-react-native-android:
72+
runs-on: macos-latest
73+
needs: check
74+
steps:
75+
- uses: actions/checkout@v2
76+
- run: npm install
77+
- uses: reactivecircus/android-emulator-runner@v2
78+
with:
79+
api-level: 29
80+
target: default
81+
arch: x86_64
82+
profile: pixel
83+
avd-name: aegir-android-29
84+
script: |
85+
npx aegir test -t react-native-android
86+
# test-react-native-ios:
87+
# runs-on: macos-latest
88+
# steps:
89+
# - uses: actions/checkout@v2
90+
# - run: npm install
91+
# - name: Create and run iOS simulator
92+
# run: |
93+
# SIMULATOR_RUNTIME=$(echo "iOS 14.4" | sed 's/[ \.]/-/g')
94+
# SIMULATOR_ID=$(xcrun simctl create "iPhone 11" com.apple.CoreSimulator.SimDeviceType.iPhone-11 com.apple.CoreSimulator.SimRuntime.$SIMULATOR_RUNTIME)
95+
# echo "IOS_SIMULATOR=$SIMULATOR_ID" >> $GITHUB_ENV
96+
# xcrun simctl boot $SIMULATOR_ID &
97+
# - run: npx rn-test --platform ios --simulator 'iPhone 11 (14.4)' --rn 0.62.0 'test/**/*.spec.js'
98+
# - name: Shutdown iOS simulator
99+
# run: |
100+
# xcrun simctl shutdown $IOS_SIMULATOR

package.json

+10-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
"electron-fetch": false,
2121
"fs": false
2222
},
23+
"react-native": {
24+
"./src/fetch.js": "./src/fetch.rn.js",
25+
"./src/http/fetch.js": "./src/http/fetch.rn.js"
26+
},
2327
"types": "dist/src/index.d.ts",
2428
"typesVersions": {
2529
"*": {
@@ -36,6 +40,8 @@
3640
"test:node": "aegir test -t node",
3741
"test:electron": "aegir test -t electron-main",
3842
"test:electron-renderer": "aegir test -t electron-renderer",
43+
"test:react-native:android": "aegir test -t react-native-android",
44+
"test:react-native:ios": "aegir test -t react-native-ios",
3945
"lint": "aegir lint",
4046
"release": "aegir release --docs",
4147
"release-minor": "aegir release --type minor --docs",
@@ -50,24 +56,26 @@
5056
"electron-fetch": "^1.7.2",
5157
"err-code": "^3.0.1",
5258
"is-electron": "^2.2.0",
53-
"iso-url": "^1.0.0",
59+
"iso-url": "^1.1.5",
5460
"it-glob": "~0.0.11",
5561
"it-to-stream": "^1.0.0",
5662
"merge-options": "^3.0.4",
5763
"nanoid": "^3.1.20",
5864
"native-abort-controller": "^1.0.3",
5965
"native-fetch": "^3.0.0",
6066
"node-fetch": "^2.6.1",
67+
"react-native-fetch-api": "^1.0.2",
6168
"stream-to-it": "^0.2.2"
6269
},
6370
"devDependencies": {
64-
"aegir": "^33.1.0",
71+
"aegir": "^33.2.0",
6572
"delay": "^5.0.0",
6673
"events": "^3.3.0",
6774
"ipfs-unixfs": "^4.0.1",
6875
"it-all": "^1.0.4",
6976
"it-drain": "^1.0.3",
7077
"it-last": "^1.0.4",
78+
"react-native-polyfill-globals": "^3.0.0",
7179
"readable-stream": "^3.6.0",
7280
"uint8arrays": "^2.0.5",
7381
"util": "^0.12.3"

rn-test.config.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict'
2+
3+
module.exports = {
4+
require: require.resolve('./rn-test.require.js'),
5+
runner: 'mocha',
6+
modules: [
7+
'react-native-url-polyfill',
8+
'web-streams-polyfill',
9+
'text-encoding'
10+
],
11+
patches: [{
12+
path: require.resolve('react-native-polyfill-globals/patches/react-native+0.63.3.patch')
13+
}]
14+
}

rn-test.require.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict'
2+
3+
const { polyfill: polyfillReadableStream } = require('react-native-polyfill-globals/src/readable-stream')
4+
const { polyfill: polyfillURL } = require('react-native-polyfill-globals/src/url')
5+
const { polyfill: polyfillEncoding } = require('react-native-polyfill-globals/src/encoding')
6+
7+
polyfillURL()
8+
polyfillReadableStream()
9+
polyfillEncoding()

src/env.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
const isElectron = require('is-electron')
33

44
const IS_ENV_WITH_DOM = typeof window === 'object' && typeof document === 'object' && document.nodeType === 9
5+
// @ts-ignore
56
const IS_ELECTRON = isElectron()
67
const IS_BROWSER = IS_ENV_WITH_DOM && !IS_ELECTRON
78
const IS_ELECTRON_MAIN = IS_ELECTRON && !IS_ENV_WITH_DOM
@@ -10,6 +11,7 @@ const IS_NODE = typeof require === 'function' && typeof process !== 'undefined'
1011
// @ts-ignore - we either ignore worker scope or dom scope
1112
const IS_WEBWORKER = typeof importScripts === 'function' && typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope
1213
const IS_TEST = typeof process !== 'undefined' && typeof process.env !== 'undefined' && process.env.NODE_ENV === 'test'
14+
const IS_REACT_NATIVE = typeof navigator !== 'undefined' && navigator.product === 'ReactNative'
1315

1416
module.exports = {
1517
isTest: IS_TEST,
@@ -22,5 +24,6 @@ module.exports = {
2224
*/
2325
isBrowser: IS_BROWSER,
2426
isWebWorker: IS_WEBWORKER,
25-
isEnvWithDom: IS_ENV_WITH_DOM
27+
isEnvWithDom: IS_ENV_WITH_DOM,
28+
isReactNative: IS_REACT_NATIVE
2629
}

src/fetch.rn.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @ts-nocheck
2+
'use strict'
3+
// @ts-ignore
4+
const { Headers, Request, Response, fetch } = require('react-native-fetch-api')
5+
6+
/** @type {import('electron-fetch').default} */
7+
const rnFetch = fetch
8+
/** @type {import('electron-fetch').Headers} */
9+
const rnHeaders = Headers
10+
/** @type {import('electron-fetch').Request} */
11+
const rnRequest = Request
12+
/** @type {import('electron-fetch').Response} */
13+
const rnResponse = Response
14+
module.exports = rnFetch
15+
module.exports.Headers = rnHeaders
16+
module.exports.Request = rnRequest
17+
module.exports.Response = rnResponse
18+
module.exports.default = rnFetch

src/http.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ const { AbortController } = require('native-abort-controller')
99
const anySignal = require('any-signal')
1010

1111
/**
12-
* @typedef {import('./types').ExtendedResponse} ExtendedResponse
1312
* @typedef {import('stream').Readable} NodeReadableStream
14-
* @typedef {import('stream').Duplex} NodeDuplexStream
1513
* @typedef {import('./types').HTTPOptions} HTTPOptions
14+
* @typedef {import('./types').ExtendedResponse} ExtendedResponse
1615
*/
1716

1817
/**

src/http/fetch.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use strict'
22

3-
// Electron has `XMLHttpRequest` and should get the browser implementation
4-
// instead of node.
53
if (typeof XMLHttpRequest === 'function') {
4+
// Electron has `XMLHttpRequest` and should get the browser implementation
5+
// instead of node.
66
module.exports = require('./fetch.browser')
77
} else {
88
module.exports = require('./fetch.node')

src/http/fetch.node.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
'use strict'
2-
32
const { Request, Response, Headers, default: nativeFetch } = require('../fetch')
43
// @ts-ignore
54
const toStream = require('it-to-stream')
@@ -46,8 +45,7 @@ const withUploadProgress = (options) => {
4645
}
4746

4847
/**
49-
* @param {BodyInit} input
50-
* @returns {Blob | FormData | URLSearchParams | ReadableStream<Uint8Array> | string | NodeReadableStream | Buffer}
48+
* @param {BodyInit | NodeReadableStream} input
5149
*/
5250
const normalizeBody = (input) => {
5351
if (input instanceof ArrayBuffer) {

0 commit comments

Comments
 (0)