Skip to content
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

Add React Native (iOS and Android) support #91

Merged
merged 18 commits into from
May 21, 2021
Merged
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',
@@ -19,6 +17,7 @@ const esbuild = {
]
}

/** @type {import('aegir').PartialOptions} */
module.exports = {
build: {
config: esbuild
@@ -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:
@@ -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 }}
@@ -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
@@ -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": {
"*": {
@@ -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",
@@ -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"
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
@@ -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
@@ -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,
@@ -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
@@ -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
*/

/**
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')
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')
@@ -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) {
Loading