Move files from `packager/` to `local-cli`

Summary: public

This is not only to put the files on a place where it makes more sense but also to allow to use ES6 features on them as `/packager` is not whitelisted on `babel`.

Reviewed By: mkonicek

Differential Revision: D2577267

fb-gh-sync-id: b69a17c0aad349a3eda987e33d1778d97a8e1549
This commit is contained in:
Martín Bigio 2015-10-26 12:59:54 -07:00 committed by facebook-github-bot-3
parent bb7fd5ffa3
commit 213c18d221
12 changed files with 0 additions and 850 deletions

View File

@ -1,47 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
const execFile = require('child_process').execFile;
const fs = require('fs');
const path = require('path');
module.exports = function(req, res, next) {
if (req.url !== '/cpu-profile') {
next();
return;
}
console.log('Dumping CPU profile information...');
var dumpName = '/tmp/cpu-profile_' + Date.now();
fs.writeFileSync(dumpName + '.json', req.rawBody);
var cmdPath = path.join(
__dirname,
'../react-native-github/JSCLegacyProfiler/json2trace'
);
execFile(
cmdPath,
[
'-cpuprofiler',
dumpName + '.cpuprofile ' + dumpName + '.json'
],
function(error) {
if (error) {
console.error(error);
res.end('Unknown error: ' + error.message);
} else {
var response = 'Your profile was generated at\n\n' + dumpName + '.cpuprofile\n\n' +
'Open `Chrome Dev Tools > Profiles > Load` and select the profile to visualize it.';
console.log(response);
res.end(response);
}
}
);
};

View File

@ -1,178 +0,0 @@
<!doctype html>
<!--
Copyright (c) 2015-present, Facebook, Inc.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree. An additional grant
of patent rights can be found in the PATENTS file in the same directory.
-->
<html>
<head>
<meta charset=utf-8>
<!-- Fake favicon, to avoid extra request to server -->
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<title>React Native Debugger</title>
<script>
(function() {
var sessionID = window.localStorage.getItem('sessionID');
window.localStorage.removeItem('sessionID');
window.onbeforeunload = function() {
if (sessionID) {
return 'If you reload this page, it is going to break the debugging session. ' +
'You should press ⌘R in simulator to reload.';
}
};
window.addEventListener('load', function () {
if (typeof window.__REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
document.getElementById('devtools-banner').style.display = 'block';
}
});
// Alias native implementations needed by the debugger before platform-specific
// implementations are loaded into the global namespace
var debuggerSetTimeout = window.setTimeout;
var DebuggerWebSocket = window.WebSocket;
function setStatus(status) {
document.getElementById('status').innerHTML = status;
}
// This worker will run the application javascript code,
// making sure that it's run in an environment without a global
// document, to make it consistent with the JSC executor environment.
var worker = new Worker('debuggerWorker.js');
var messageHandlers = {
// This method is a bit hacky. Catalyst asks for a new clean JS runtime.
// The easiest way to do this is to reload this page. That also means that
// web socket connection will be lost. To send reply back we need to remember
// message id.
// This message also needs to be handled outside of the worker, since the worker
// doesn't have access to local storage.
'prepareJSRuntime': function(message) {
window.onbeforeunload = undefined;
window.localStorage.setItem('sessionID', message.id);
window.location.reload();
},
'executeApplicationScript': function(message) {
worker.postMessage(message);
},
'executeJSCall': function(message) {
worker.postMessage(message);
}
};
function connectToDebuggerProxy() {
var ws = new DebuggerWebSocket('ws://' + window.location.host + '/debugger-proxy');
ws.onopen = function() {
if (sessionID) {
setStatus('Debugger session #' + sessionID + ' active.');
ws.send(JSON.stringify({replyID: parseInt(sessionID, 10)}));
} else {
setStatus('Waiting, press <span class="shortcut">⌘R</span> in simulator to reload and connect.');
}
};
ws.onmessage = function(message) {
var object = JSON.parse(message.data);
if (!object.method) {
return;
}
var handler = messageHandlers[object.method];
if (handler) {
handler(object);
} else {
console.warn('Unknown method: ' + object.method);
}
};
ws.onclose = function() {
setStatus('Disconnected from proxy. Attempting reconnection. Is node server running?');
sessionID = null;
window.localStorage.removeItem('sessionID');
debuggerSetTimeout(connectToDebuggerProxy, 100);
};
worker.onmessage = function(message) {
ws.send(JSON.stringify(message.data));
}
}
connectToDebuggerProxy();
})();
</script>
<style type="text/css">
body {
font-size: large;
margin: 0;
padding: 0;
font-family: Helvetica, Verdana, sans-serif;
font-weight: 200;
}
.shortcut {
font-family: "Monaco", monospace;
font-size: medium;
color: #eee;
background-color: #333;
padding: 4px;
border-radius: 4px;
letter-spacing: 3px;
}
#devtools-banner {
display: none;
background-color: #FDFDD5;
padding: 10px;
}
#devtools-banner h3 {
margin: 0;
font-weight: normal;
}
#devtools-banner a {
display: none;
padding: 10px 20px 10px 20px;
margin-bottom: 10px;
color: white;
text-decoration: none;
font-size: 11px;
text-shadow: 0 1px 1px rgba(0,0,0,0.1);
text-transform: uppercase;
font-weight: bold;
background-color: #4d7bd6;
border-radius: 2px;
border: 1px solid #2d53af;
display: inline-block;
}
.content {
padding: 10px;
}
</style>
</head>
<body>
<div id="devtools-banner">
<h3>Install React DevTools</h3>
<p>
React Developer Tools is an extension that allows you to inspect the
React component hierarchies in the Chrome Developer Tools.
</p>
<a href="https://fb.me/react-devtools" target="_blank">
Install
</a>
</div>
<div class="content">
<p>
React Native JS code runs inside this Chrome tab.
</p>
<p>Press <span class="shortcut">⌘⌥J</span> to open Developer Tools. Enable <a href="http://stackoverflow.com/a/17324511/232122" target="_blank">Pause On Caught Exceptions</a> for a better debugging experience.</p>
<p>Status: <span id="status">Loading...</span></p>
</div>
</body>
</html>

View File

@ -1,46 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/* global self, importScripts, postMessage, onmessage: true */
/* eslint no-unused-vars: 0 */
'use strict';
var messageHandlers = {
'executeApplicationScript': function(message, sendReply) {
for (var key in message.inject) {
self[key] = JSON.parse(message.inject[key]);
}
importScripts(message.url);
sendReply();
},
'executeJSCall': function(message, sendReply) {
var returnValue = [[], [], [], [], []];
try {
if (require) {
returnValue = require(message.moduleName)[message.moduleMethod].apply(null, message.arguments);
}
} finally {
sendReply(JSON.stringify(returnValue));
}
}
};
onmessage = function(message) {
var object = message.data;
var sendReply = function(result) {
postMessage({replyID: object.id, result: result});
};
var handler = messageHandlers[object.method];
if (handler) {
handler(object, sendReply);
} else {
console.warn('Unknown method: ' + object.method);
}
};

View File

@ -1,61 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
var execFile = require('child_process').execFile;
var fs = require('fs');
var opn = require('opn');
var path = require('path');
function getChromeAppName() {
switch (process.platform) {
case 'darwin':
return 'google chrome';
case 'win32':
return 'chrome';
default:
return 'google-chrome';
}
}
module.exports = function(options, isDebuggerConnected) {
return function(req, res, next) {
if (req.url === '/debugger-ui') {
var debuggerPath = path.join(__dirname, 'debugger.html');
res.writeHead(200, {'Content-Type': 'text/html'});
fs.createReadStream(debuggerPath).pipe(res);
} else if (req.url === '/debuggerWorker.js') {
var workerPath = path.join(__dirname, 'debuggerWorker.js');
res.writeHead(200, {'Content-Type': 'application/javascript'});
fs.createReadStream(workerPath).pipe(res);
} else if (req.url === '/launch-safari-devtools') {
// TODO: remove `console.log` and dev tools binary
console.log(
'We removed support for Safari dev-tools. ' +
'If you still need this, please let us know.'
);
} else if (req.url === '/launch-chrome-devtools') {
if (isDebuggerConnected()) {
// Dev tools are already open; no need to open another session
res.end('OK');
return;
}
var debuggerURL = 'http://localhost:' + options.port + '/debugger-ui';
console.log('Launching Dev Tools...');
opn(debuggerURL, {app: [getChromeAppName()]}, function(err) {
if (err) {
console.error('Google Chrome exited with error:', err);
}
});
res.end('OK');
} else {
next();
}
};
};

View File

@ -1,150 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
var chalk = require('chalk');
var exec = require('child_process').exec;
var url = require('url');
var Activity = require('./react-packager').Activity;
var hasWarned = {};
function getFlowTypeCheckMiddleware(options) {
return function(req, res, next) {
var reqObj = url.parse(req.url);
var isFlowCheck = (reqObj.path.match(/^\/flow\//));
if (!isFlowCheck) {
return next();
}
if (options.skipflow) {
_endSkipFlow(res);
return;
}
if (options.flowroot || options.projectRoots.length === 1) {
var flowroot = options.flowroot || options.projectRoots[0];
} else {
if (!hasWarned.noRoot) {
hasWarned.noRoot = true;
console.warn('flow: No suitable root');
}
_endFlowBad(res);
return;
}
exec('command -v flow >/dev/null 2>&1', function(error, stdout) {
if (error) {
if (!hasWarned.noFlow) {
hasWarned.noFlow = true;
console.warn(chalk.yellow('flow: Skipping because not installed. Install with ' +
'`brew install flow`.'));
}
_endFlowBad(res);
return;
} else {
return doFlowTypecheck(res, flowroot, next);
}
});
};
}
function doFlowTypecheck(res, flowroot, next) {
var flowCmd = 'cd "' + flowroot + '" && flow --json --timeout 20';
var eventId = Activity.startEvent('flow static typechecks');
exec(flowCmd, function(flowError, stdout, stderr) {
Activity.endEvent(eventId);
if (!flowError) {
_endFlowOk(res);
return;
} else {
try {
var flowResponse = JSON.parse(stdout);
var errors = [];
var errorNum = 1;
flowResponse.errors.forEach(function(err) {
// flow errors are paired across callsites, so we indent and prefix to
// group them
var indent = '';
err.message.forEach(function(msg) {
errors.push({
description: indent + 'E' + errorNum + ': ' + msg.descr,
filename: msg.path,
lineNumber: msg.line,
column: msg.start,
});
indent = ' ';
});
errorNum++;
});
var error = {
status: 200,
message: 'Flow found type errors. If you think these are wrong, ' +
'make sure your flow bin and .flowconfig are up to date, or ' +
'disable with --skipflow.',
type: 'FlowError',
errors: errors,
};
res.writeHead(error.status, {
'Content-Type': 'application/json; charset=UTF-8',
});
res.end(JSON.stringify(error));
} catch (e) {
if (stderr.match(/Could not find a \.flowconfig/)) {
if (!hasWarned.noConfig) {
hasWarned.noConfig = true;
console.warn(chalk.yellow('flow: ' + stderr));
}
_endFlowBad(res);
} else if (flowError.code === 3) {
if (!hasWarned.timeout) {
hasWarned.timeout = true;
console.warn(chalk.yellow('flow: ' + stdout));
}
_endSkipFlow(res);
} else {
if (!hasWarned.brokenFlow) {
hasWarned.brokenFlow = true;
console.warn(chalk.yellow(
'Flow failed to provide parseable output:\n\n`' + stdout +
'`.\n' + 'stderr: `' + stderr + '`'
));
}
_endFlowBad(res);
}
return;
}
}
});
}
function _endRes(res, message, code, silentError) {
res.writeHead(code, {
'Content-Type': 'application/json; charset=UTF-8',
});
res.end(JSON.stringify({
message: message,
errors: [],
silentError: silentError,
}));
}
function _endFlowOk(res) {
_endRes(res, 'No Flow Error', '200', true);
}
function _endFlowBad(res) {
// we want to show that flow failed
// status 200 is need for the fetch to not be rejected
_endRes(res, 'Flow failed to run! Please look at the console for more details.', '200', false);
}
function _endSkipFlow(res) {
_endRes(res, 'Flow was skipped, check the server options', '200', true);
}
module.exports = getFlowTypeCheckMiddleware;

View File

@ -1,103 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
var chalk = require('chalk');
var fs = require('fs');
var spawn = require('child_process').spawn;
function isTerminalEditor(editor) {
switch (editor) {
case 'vim':
case 'emacs':
case 'nano':
return true;
}
return false;
}
function getArgumentsForLineNumber(editor, fileName, lineNumber) {
switch (editor) {
case 'vim':
case 'mvim':
return [fileName, '+' + lineNumber];
case 'atom':
case 'subl':
case 'sublime':
return [fileName + ':' + lineNumber];
case 'joe':
case 'emacs':
case 'emacsclient':
return ['+' + lineNumber, fileName];
case 'rmate':
case 'mate':
return ['--line', lineNumber, fileName];
}
// For all others, drop the lineNumber until we have
// a mapping above, since providing the lineNumber incorrectly
// can result in errors or confusing behavior.
return [fileName];
}
function printInstructions(title) {
console.log([
'',
chalk.bgBlue.white.bold(' ' + title + ' '),
' When you see Red Box with stack trace, you can click any ',
' stack frame to jump to the source file. The packager will launch your ',
' editor of choice. It will first look at REACT_EDITOR environment ',
' variable, then at EDITOR. To set it up, you can add something like ',
' REACT_EDITOR=atom to your .bashrc.',
''
].join('\n'));
}
var _childProcess = null;
function launchEditor(fileName, lineNumber) {
if (!fs.existsSync(fileName)) {
return;
}
var editor = process.env.REACT_EDITOR || process.env.EDITOR;
if (!editor) {
printInstructions('PRO TIP');
return;
}
var args = [fileName];
if (lineNumber) {
args = getArgumentsForLineNumber(editor, fileName, lineNumber);
}
console.log('Opening ' + chalk.underline(fileName) + ' with ' + chalk.bold(editor));
if (_childProcess && isTerminalEditor(editor)) {
// There's an existing editor process already and it's attached
// to the terminal, so go kill it. Otherwise two separate editor
// instances attach to the stdin/stdout which gets confusing.
_childProcess.kill('SIGKILL');
}
_childProcess = spawn(editor, args, {stdio: 'inherit'});
_childProcess.on('exit', function(errorCode) {
_childProcess = null;
if (errorCode) {
console.log(chalk.red('Your editor exited with an error!'));
printInstructions('Keep these instructions in mind:');
}
});
_childProcess.on('error', function(error) {
console.log(chalk.red(error.message));
printInstructions('How to fix:');
})
}
module.exports = launchEditor;

View File

@ -1,22 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
module.exports = function(req, res, next) {
req.rawBody = '';
req.setEncoding('utf8');
req.on('data', function(chunk) {
req.rawBody += chunk;
});
req.on('end', function() {
next();
});
};

View File

@ -1,21 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
const launchEditor = require('./launchEditor');
module.exports = function(req, res, next) {
if (req.url === '/open-stack-frame') {
var frame = JSON.parse(req.rawBody);
launchEditor(frame.file, frame.lineNumber);
res.end('OK');
} else {
next();
}
};

View File

@ -1,76 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* Wrapper on-top of `optimist` in order to properly support boolean flags
* and have a slightly less akward API.
*
* Usage example:
* var argv = parseCommandLine([{
* command: 'web',
* description: 'Run in a web browser instead of iOS',
* default: true
* }])
*/
'use strict';
var optimist = require('optimist');
function parseCommandLine(config, args) {
args = args || process.argv;
// optimist default API requires you to write the command name three time
// This is a small wrapper to accept an object instead
for (var i = 0; i < config.length; ++i) {
if (config[i].type === 'string') {
optimist.string(config[i].command);
} else {
optimist.boolean(config[i].command);
}
optimist
.default(config[i].command, config[i].default)
.describe(config[i].command, config[i].description);
if (config[i].required) {
optimist.demand(config[i].command);
}
}
var argv = optimist.parse(args);
// optimist doesn't have support for --dev=false, instead it returns 'false'
for (var i = 0; i < config.length; ++i) {
var command = config[i].command;
if (argv[command] === undefined) {
argv[command] = config[i].default;
}
if (argv[command] === 'true') {
argv[command] = true;
}
if (argv[command] === 'false') {
argv[command] = false;
}
if (config[i].type === 'string') {
// According to https://github.com/substack/node-optimist#numbers,
// every argument that looks like a number should be converted to one.
var strValue = argv[command];
var numValue = strValue ? Number(strValue) : undefined;
if (typeof numValue === 'number' && !isNaN(numValue)) {
argv[command] = numValue;
}
}
}
// Show --help
if (argv.help || argv.h) {
optimist.showHelp();
process.exit();
}
return argv;
}
module.exports = parseCommandLine;

View File

@ -1,21 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
/**
* Status page so that anyone who needs to can verify that the packager is
* running on 8081 and not another program / service.
*/
module.exports = function(req, res, next) {
if (req.url === '/status') {
res.end('packager-status:running');
} else {
next();
}
};

View File

@ -1,52 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
const exec = require('child_process').exec;
const fs = require('fs');
const path = require('path');
module.exports = function(req, res, next) {
if (req.url !== '/systrace') {
next();
return;
}
console.log('Dumping profile information...');
var dumpName = '/tmp/dump_' + Date.now() + '.json';
var prefix = process.env.TRACE_VIEWER_PATH || '';
var cmd = path.join(prefix, 'trace2html') + ' ' + dumpName;
fs.writeFileSync(dumpName, req.rawBody);
exec(cmd, function(error) {
if (error) {
if (error.code === 127) {
var response = '\n** Failed executing `' + cmd + '` **\n\n' +
'Google trace-viewer is required to visualize the data, ' +
'You can install it with `brew install trace2html`\n\n' +
'NOTE: Your profile data was kept at:\n' + dumpName;
console.log(response);
res.end(response);
} else {
console.error(error);
res.end('Unknown error: ' + error.message);
}
return;
} else {
exec('rm ' + dumpName);
exec('open ' + dumpName.replace(/json$/, 'html'), function(err) {
if (err) {
console.error(err);
res.end(err.message);
} else {
res.end();
}
});
}
});
};

View File

@ -1,73 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
function attachToServer(server, path) {
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({
server: server,
path: path
});
var clients = [];
function sendSpecial(message) {
clients.forEach(function (cn) {
try {
cn.send(JSON.stringify(message));
} catch(e) {
// Sometimes this call throws 'not opened'
}
});
}
wss.on('connection', function(ws) {
var id = Math.random().toString(15).slice(10, 20);
sendSpecial({$open: id});
clients.push(ws);
var allClientsExcept = function(ws) {
return clients.filter(function(cn) { return cn !== ws; });
};
ws.onerror = function() {
clients = allClientsExcept(ws);
sendSpecial({$error: id});
};
ws.onclose = function() {
clients = allClientsExcept(ws);
sendSpecial({$close: id});
};
ws.on('message', function(message) {
allClientsExcept(ws).forEach(function(cn) {
try {
cn.send(message);
} catch(e) {
// Sometimes this call throws 'not opened'
}
});
});
});
return {
server: wss,
isChromeConnected: function() {
return clients
.map(function(ws) { return ws.upgradeReq.headers['user-agent']; })
.filter(Boolean)
.some(function(userAgent) { return userAgent.includes('Chrome'); })
}
};
}
module.exports = {
attachToServer: attachToServer
};