diff --git a/packager/packager.js b/packager/packager.js index b75ccaa26..b9e302005 100644 --- a/packager/packager.js +++ b/packager/packager.js @@ -68,6 +68,10 @@ var options = parseCommandLine([{ command: 'reset-cache', description: 'Removes cached files', default: false, +}, { + command: 'verbose', + description: 'Enables logging', + default: false, }]); if (options.projectRoots) { @@ -187,6 +191,7 @@ function getAppMiddleware(options) { '../Libraries/JavaScriptAppEngine/polyfills/document.js' ), ], + verbose: options.verbose, }); } diff --git a/packager/react-packager/index.js b/packager/react-packager/index.js index 64ad19857..e0a29684d 100644 --- a/packager/react-packager/index.js +++ b/packager/react-packager/index.js @@ -12,12 +12,12 @@ require('../babelRegisterOnly')([/react-packager\/src/]); useGracefulFs(); +var debug = require('debug'); +var omit = require('underscore').omit; var Activity = require('./src/Activity'); -var Server = require('./src/Server'); -var SocketInterface = require('./src/SocketInterface'); exports.middleware = function(options) { - var server = new Server(options); + var server = createServer(options); return server.processRequest.bind(server); }; @@ -27,7 +27,7 @@ exports.Activity = Activity; // compat. exports.buildPackage = exports.buildBundle = function(options, bundleOptions) { - var server = createServer(options); + var server = createNonPersistentServer(options); return server.buildBundle(bundleOptions) .then(function(p) { server.end(); @@ -37,7 +37,7 @@ exports.buildBundle = function(options, bundleOptions) { exports.buildPackageFromUrl = exports.buildBundleFromUrl = function(options, reqUrl) { - var server = createServer(options); + var server = createNonPersistentServer(options); return server.buildBundleFromUrl(reqUrl) .then(function(p) { server.end(); @@ -46,7 +46,7 @@ exports.buildBundleFromUrl = function(options, reqUrl) { }; exports.getDependencies = function(options, bundleOptions) { - var server = createServer(options); + var server = createNonPersistentServer(options); return server.getDependencies(bundleOptions) .then(function(r) { server.end(); @@ -55,23 +55,70 @@ exports.getDependencies = function(options, bundleOptions) { }; exports.createClientFor = function(options) { - return SocketInterface.getOrCreateSocketFor(options); + if (options.verbose) { + enableDebug(); + } + startSocketInterface(); + return ( + require('./src/SocketInterface') + .getOrCreateSocketFor(omit(options, ['verbose'])) + ); }; -SocketInterface.listenOnServerMessages(); - function useGracefulFs() { var fs = require('fs'); var gracefulFs = require('graceful-fs'); gracefulFs.gracefulify(fs); } +function enableDebug() { + // react-packager logs debug messages using the 'debug' npm package, and uses + // the following prefix throughout. + // To enable debugging, we need to set our pattern or append it to any + // existing pre-configured pattern to avoid disabling logging for + // other packages + var debugPattern = 'ReactNativePackager:*'; + var existingPattern = debug.load(); + if (existingPattern) { + debugPattern += ',' + existingPattern; + } + debug.enable(debugPattern); +} + function createServer(options) { + // the debug module is configured globally, we need to enable debugging + // *before* requiring any packages that use `debug` for logging + if (options.verbose) { + enableDebug(); + } + + startSocketInterface(); + var Server = require('./src/Server'); + return new Server(omit(options, ['verbose'])); +} + +function createNonPersistentServer(options) { Activity.disable(); // Don't start the filewatcher or the cache. if (options.nonPersistent == null) { options.nonPersistent = true; } - return new Server(options); + return createServer(options); +} + +// we need to listen on a socket as soon as a server is created, but only once. +// This file also serves as entry point when spawning a socket server; in that +// case we need to start the server immediately. +var didStartSocketInterface = false; +function startSocketInterface() { + if (didStartSocketInterface) { + return; + } + didStartSocketInterface = true; + require('./src/SocketInterface').listenOnServerMessages(); +} + +if (require.main === module) { // used as entry point + startSocketInterface(); } diff --git a/packager/react-packager/src/SocketInterface/index.js b/packager/react-packager/src/SocketInterface/index.js index 2a885b1cb..c56026ead 100644 --- a/packager/react-packager/src/SocketInterface/index.js +++ b/packager/react-packager/src/SocketInterface/index.js @@ -27,10 +27,11 @@ const SocketInterface = { return new Promise((resolve, reject) => { const hash = crypto.createHash('md5'); Object.keys(options).sort().forEach(key => { - if (options[key] && typeof options[key] !== 'string') { - hash.update(JSON.stringify(options[key])); - } else { - hash.update(options[key]); + const value = options[key]; + if (value) { + hash.update( + typeof value === 'string' ? value : JSON.stringify(value) + ); } }); diff --git a/private-cli/src/bundle/bundle.js b/private-cli/src/bundle/bundle.js index 9ea1aa93d..7a039cf4e 100644 --- a/private-cli/src/bundle/bundle.js +++ b/private-cli/src/bundle/bundle.js @@ -58,7 +58,11 @@ function _bundle(argv, config, resolve, reject) { command: 'assets-dest', description: 'Directory name where to store assets referenced in the bundle', type: 'string', - } + }, { + command: 'verbose', + description: 'Enables logging', + default: false, + }, ], argv); // This is used by a bazillion of npm modules we don't control so we don't @@ -70,6 +74,7 @@ function _bundle(argv, config, resolve, reject) { assetRoots: config.getAssetRoots(), blacklistRE: config.getBlacklistRE(args.platform), transformModulePath: args.transformer, + verbose: args.verbose, }; const requestOpts = { diff --git a/private-cli/src/dependencies/dependencies.js b/private-cli/src/dependencies/dependencies.js index 893a8ce6d..f883dbc0a 100644 --- a/private-cli/src/dependencies/dependencies.js +++ b/private-cli/src/dependencies/dependencies.js @@ -44,6 +44,10 @@ function _dependencies(argv, config, resolve, reject) { type: 'string', default: require.resolve('../../../packager/transformer'), description: 'Specify a custom transformer to be used (absolute path)' + }, { + command: 'verbose', + description: 'Enables logging', + default: false, } ], argv); @@ -57,6 +61,7 @@ function _dependencies(argv, config, resolve, reject) { assetRoots: config.getAssetRoots(), blacklistRE: config.getBlacklistRE(args.platform), transformModulePath: args.transformer, + verbose: config.verbose, }; const relativePath = packageOpts.projectRoots.map(root => diff --git a/private-cli/src/server/runServer.js b/private-cli/src/server/runServer.js index 7f33d83db..9071dc140 100644 --- a/private-cli/src/server/runServer.js +++ b/private-cli/src/server/runServer.js @@ -62,6 +62,7 @@ function getAppMiddleware(args, config) { '../../../Libraries/JavaScriptAppEngine/polyfills/document.js' ), ], + verbose: args.verbose, }); } diff --git a/private-cli/src/server/server.js b/private-cli/src/server/server.js index fe7c23abf..65ffe8acd 100644 --- a/private-cli/src/server/server.js +++ b/private-cli/src/server/server.js @@ -58,6 +58,10 @@ function _server(argv, config, resolve, reject) { command: 'reset-cache', description: 'Removes cached files', default: false, + }, { + command: 'verbose', + description: 'Enables logging', + default: false, }]); args.projectRoots = args.projectRoots