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-debugger-open patch #3

Merged
merged 8 commits into from
Jun 3, 2016
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
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