Skip to content

Commit

Permalink
Merge pull request #3 from jhen0409/patch-for-rn
Browse files Browse the repository at this point in the history
Add `react-native-debugger-open` patch
  • Loading branch information
jhen0409 committed Jun 3, 2016
2 parents 928b060 + 6372bc8 commit fa912bb
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 12 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ $ brew update && brew cask install react-native-debugger

Make sure all `http://localhost:8081/debugger-ui` pages is closed, open the app to wait state, and reload JS with your simulator/device.

Also, you can use [react-native-debugger-patch](https://github.com/jhen0409/react-native-debugger/blob/master/patch), it will replace `open debugger-ui with Chrome` to `open React Native Debugger` from react-native packager.

## Debugger

This is reference to [react-native](https://github.com/facebook/react-native/blob/master/local-cli/server/util/) debugger-ui.
Expand Down
28 changes: 25 additions & 3 deletions app/containers/Debugger/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Component, PropTypes } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as debuggerAtions from '../../actions/debugger';
import { ipcRenderer } from 'electron';

const INITIAL_MESSAGE = 'Waiting, press ⌘R in simulator to reload and connect.';

Expand All @@ -39,14 +40,33 @@ export default class Debugger extends Component {
};

componentDidMount() {
this.socket = this.connectToDebuggerProxy();
this.setDebuggerLoc(JSON.parse(process.env.DEBUGGER_SETTING || '{}'));

ipcRenderer.on('set-debugger-loc', (e, payload) => {
this.setDebuggerLoc(JSON.parse(payload));
});
}

componentWillUnmount() {
this.socket.close();
}

connectToDebuggerProxy = (host = 'localhost', port = 8081) => {
setDebuggerLoc({ host, port }) {
if (this.host === host && this.port === Number(port)) return;

this.host = host;
this.port = port;
if (this.socket) {
this.socket.close();
} else {
this.socket = this.connectToDebuggerProxy();
}
}

connectToDebuggerProxy = () => {
const host = this.host || 'localhost';
const port = this.port || 8081;

const ws = WebSocket.connect(`ws://${host}:${port}/debugger-proxy?role=debugger&name=Chrome`);

const onmessage = message => {
Expand Down Expand Up @@ -123,7 +143,9 @@ export default class Debugger extends Component {
setStatusToTitle(e.reason);
console.warn(e.reason);
}
setTimeout(this.connectToDebuggerProxy, 500);
setTimeout(() => {
this.socket = this.connectToDebuggerProxy();
}, 500);
};
return ws;
}
Expand Down
19 changes: 19 additions & 0 deletions electron/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const { app, BrowserWindow, Menu, shell } = require('electron');
const url = require('url');
const qs = require('querystring');

let menu;
let template;
Expand All @@ -8,6 +10,23 @@ app.on('window-all-closed', () => {
app.quit();
});

app.on('open-url', (e, path) => {
const route = url.parse(path);

if (route.host !== 'set-debugger-loc') return;

const { host, port } = qs.parse(route.query);
const payload = JSON.stringify({
host: host || 'localhost',
port: Number(port) || 8081,
});
if (mainWindow) {
mainWindow.webContents.send('set-debugger-loc', payload);
} else {
process.env.DEBUGGER_SETTING = payload;
}
});

app.on('ready', () => {
mainWindow = new BrowserWindow({ width: 1024, height: 750, show: false });

Expand Down
10 changes: 1 addition & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,13 @@
"build": "cp electron/main.js dist/main.js && npm run build:app",
"dev:webpack": "npm run build:devtools && webpack-dev-server --config webpack/dev.babel.js --hot --inline --colors",
"dev:electron": "electron .",
"lint": "eslint app/ electron/ webpack/",
"lint": "eslint app/ electron/ webpack/ patch/lib",
"postinstall": "./scripts/postinstall.sh"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jhen0409/react-native-debugger.git"
},
"keywords": [
"react",
"react-native",
"debugger",
"react-devtools",
"redux-devtools",
"desktop"
],
"author": "Jhen <developer@jhen.me>",
"license": "MIT",
"devDependencies": {
Expand Down
48 changes: 48 additions & 0 deletions patch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# react-native-debugger-open

> Replace `open debugger-ui with Chrome` to `open React Native Debugger` from react-native packager
__*NOTE*__ This patch is only work with `react-native-debugger@^0.2.0`.

## Screenshot

![demo](https://cloud.githubusercontent.com/assets/3001525/15777379/59a9c654-29c1-11e6-8656-247b8450bc47.gif)

## Installation

First, install [React Native Debugger](https://github.com/jhen0409/react-native-debugger#usage).

In your React Native project:

```bash
$ npm i --save-dev react-native-debugger-open
```

## Usage

Add command to your project's package.json:

```
"scripts": {
"postinstall": "rndebugger-open"
}
```

It will be run after `npm install`. (You can run `npm run postinstall` first)

If you want to revert injection, just run:

```bash
$ $(npm bin)/rndebugger-open --revert
```

You can also use following command instead of this patch:

```bash
# OS X
$ open "rndebugger://set-debugger-loc?host=localhost&port=8082"
```

## LICENSE

[MIT](https://github.com/jhen0409/react-native-debugger/blob/master/LICENSE.md)
12 changes: 12 additions & 0 deletions patch/bin/rndebugger-open.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#! /usr/bin/env node

const argv = require('minimist')(process.argv.slice(2), {
boolean: ['inject', 'revert', 'desktop'],
default: {
inject: true,
},
});

require('../lib/main')(argv, (pass) => {
if (!pass) process.exit(1);
});
69 changes: 69 additions & 0 deletions patch/lib/injectDevToolsMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use strict';

const fs = require('fs');
const path = require('path');

const name = 'react-native-debugger-patch';
const startFlag = `/* ${name} start */`;
const endFlag = `/* ${name} end */`;
const funcFlag = 'function launchChromeDevTools(port) {';

exports.dir = 'local-cli/server/middleware';
exports.file = 'getDevToolsMiddleware.js';
exports.fullPath = path.join(exports.dir, exports.file);

exports.inject = modulePath => {
const filePath = path.join(modulePath, exports.fullPath);
if (!fs.existsSync(filePath)) return false;

const code = [
startFlag,
'var _rndebuggerIsOpening = false;',
funcFlag,
' if (process.platform === "darwin") {',
' if (_rndebuggerIsOpening) return;',
' _rndebuggerIsOpening = true;',
' opn("rndebugger://set-debugger-loc?host=localhost&port=" + port, { wait: false }, err => {',
' if (err) {',
' console.log(',
' "\\nCannot open React Native Debugger, maybe not install?\\n" +',
' "(Please visit https://github.com/jhen0409/react-native-debugger#usage)\\n" +',
' "Or it\'s never started. (Not registered URI Scheme)\\n"',
' );',
' }',
' _rndebuggerIsOpening = false;',
' });',
' return;',
' }',
endFlag,
].join('\n');

const middlewareCode = fs.readFileSync(filePath, 'utf-8');
let start = middlewareCode.indexOf(startFlag); // already injected ?
let end = middlewareCode.indexOf(endFlag) + endFlag.length;
if (start === -1) {
start = middlewareCode.indexOf(funcFlag);
end = start + funcFlag.length;
}
fs.writeFileSync(
filePath,
middlewareCode.substr(0, start) + code + middlewareCode.substr(end, middlewareCode.length)
);
return true;
};

exports.revert = modulePath => {
const filePath = path.join(modulePath, exports.fullPath);
if (!fs.existsSync(filePath)) return false;

const middlewareCode = fs.readFileSync(filePath, 'utf-8');
const start = middlewareCode.indexOf(startFlag); // already injected ?
const end = middlewareCode.indexOf(endFlag) + endFlag.length;
if (start !== -1) {
fs.writeFileSync(
filePath,
middlewareCode.substr(0, start) + funcFlag + middlewareCode.substr(end, middlewareCode.length)
);
}
return true;
};
60 changes: 60 additions & 0 deletions patch/lib/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const fs = require('fs');
const cp = require('child_process');
const path = require('path');
const chalk = require('chalk');
const injectDevToolsMiddleware = require('./injectDevToolsMiddleware');

const name = 'react-native';

const getModulePath = moduleName =>
path.join(process.cwd(), 'node_modules', moduleName);

const log = (pass, msg) => {
const prefix = pass ? chalk.green.bgBlack('PASS') : chalk.red.bgBlack('FAIL');
const color = pass ? chalk.blue : chalk.red;
console.log(prefix, color(msg));
};

module.exports = (argv, cb) => {
const modulePath = getModulePath(argv.desktop ? 'react-native-desktop' : name);

// Revert injection
if (argv.revert) {
const passMiddleware = injectDevToolsMiddleware.revert(modulePath);
const msg = 'Revert injection of React Native Debugger from React Native packager';
log(
passMiddleware,
msg + (!passMiddleware ? `, the file '${injectDevToolsMiddleware.path}' not found.` : '.')
);
return cb(passMiddleware);
}

const inject = () => {
const pass = injectDevToolsMiddleware.inject(modulePath);
const msg = 'Replace `open debugger-ui with Chrome` to `open React Native Debugger`';
log(pass, msg + (pass ? '.' : `, the file '${injectDevToolsMiddleware.path}' not found.`));
cb(pass);
};

if (process.platform !== 'darwin') {
inject();
} else {
const cwd = '/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/'; // eslint-disable-line
const lsregisterPath = 'lsregister';
if (!fs.existsSync(cwd + lsregisterPath)) return inject();

cp.exec(`./${lsregisterPath} -dump | grep rndebugger:`, { cwd }, (err, stdout) => {
if (stdout.length === 0) {
log(
false,
'Cannot find `rndebugger` URI Scheme, ' +
'maybe not install React Native Debugger? ' +
'(Please visit https://github.com/jhen0409/react-native-debugger#usage) ' +
'Or it\'s never started. (Not registered URI Scheme)'
);
return cb(false);
}
inject();
});
}
};
25 changes: 25 additions & 0 deletions patch/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "react-native-debugger-open",
"version": "0.2.0",
"description": "Replace `open debugger-ui with Chrome` to `open React Native Debugger` from react-native packager",
"bin": {
"rndebugger-open": "bin/rndebugger-open.js"
},
"scripts": {},
"homepage": "https://github.com/jhen0409/react-native-debugger",
"repository": "https://github.com/jhen0409/react-native-debugger/tree/master/patch",
"keywords": [
"react",
"react-native",
"debugger",
"react-devtools",
"redux-devtools",
"electron"
],
"author": "Jhen <developer@jhen.me>",
"license": "MIT",
"dependencies": {
"chalk": "^1.1.3",
"minimist": "^1.2.0"
}
}
2 changes: 2 additions & 0 deletions scripts/package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ electron-packager dist/ \
--asar \
--prune \
--out release \
--protocol-name "React Native Debugger" \
--protocol "rndebugger" \
--app-version $(node -p -e "require('./package.json').version") \
--app-copyright "This software is included following project: https://github.com/facebook/react-devtools, https://github.com/zalmoxisus/remotedev-app" \
--icon electron/logo.icns

0 comments on commit fa912bb

Please sign in to comment.