Skip to content

Add React Native (iOS and Android) support #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
May 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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