mirror of https://github.com/status-im/metro.git
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:
parent
bb7fd5ffa3
commit
213c18d221
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
178
debugger.html
178
debugger.html
|
@ -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>
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -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;
|
|
103
launchEditor.js
103
launchEditor.js
|
@ -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;
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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;
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -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
|
|
||||||
};
|
|
Loading…
Reference in New Issue