"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _chalk() { const data = _interopRequireDefault(require("chalk")); _chalk = function () { return data; }; return data; } function _getenv() { const data = _interopRequireDefault(require("getenv")); _getenv = function () { return data; }; return data; } function ProjectUtils() { const data = _interopRequireWildcard(require("../project/ProjectUtils")); ProjectUtils = function () { return data; }; return data; } function _Logger() { const data = _interopRequireDefault(require("../Logger")); _Logger = function () { return data; }; return data; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } class PackagerLogsStream { constructor({ projectRoot, getCurrentOpenProjectId, updateLogs, onStartBuildBundle, onProgressBuildBundle, onFinishBuildBundle, getSnippetForError }) { _defineProperty(this, "_projectRoot", void 0); _defineProperty(this, "_getCurrentOpenProjectId", void 0); _defineProperty(this, "_updateLogs", void 0); _defineProperty(this, "_logsToAdd", []); _defineProperty(this, "_bundleBuildChunkID", null); _defineProperty(this, "_onStartBuildBundle", void 0); _defineProperty(this, "_onProgressBuildBundle", void 0); _defineProperty(this, "_onFinishBuildBundle", void 0); _defineProperty(this, "_bundleBuildStart", null); _defineProperty(this, "_getSnippetForError", void 0); _defineProperty(this, "_handleBundleTransformEvent", chunk => { const msg = chunk.msg; if (msg.type === 'bundle_build_started') { chunk._metroEventType = 'BUILD_STARTED'; this._handleNewBundleTransformStarted(chunk); } else if (msg.type === 'bundle_transform_progressed') { chunk._metroEventType = 'BUILD_PROGRESS'; if (this._bundleBuildChunkID) { this._handleUpdateBundleTransformProgress(chunk); } else { this._handleNewBundleTransformStarted(chunk); } } else if (msg.type === 'bundle_build_failed') { chunk._metroEventType = 'BUILD_FAILED'; if (!this._bundleBuildChunkID) {// maybe? } else { this._handleUpdateBundleTransformProgress(chunk); } } else if (msg.type === 'bundle_build_done') { chunk._metroEventType = 'BUILD_DONE'; if (!this._bundleBuildChunkID) {// maybe? } else { this._handleUpdateBundleTransformProgress(chunk); } } }); _defineProperty(this, "_enqueueFlushLogsToAdd", () => { this._updateLogs(logs => { if (this._logsToAdd.length === 0) { return logs; } let nextLogs = logs.concat(this._logsToAdd); this._logsToAdd = []; return nextLogs; }); }); _defineProperty(this, "_cleanUpNodeErrors", chunk => { if (typeof chunk.msg === 'object') { return chunk; } if (chunk.msg.match(/\(node:.\d*\)/)) { // Example: (node:13817) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): SyntaxError: SyntaxError /Users/brent/universe/apps/new-project-template/main.js: Unexpected token (10:6) // The first part of this is totally useless, so let's remove it. if (chunk.msg.match(/UnhandledPromiseRejectionWarning/)) { chunk.msg = chunk.msg.replace(/\(node:.*\(rejection .*\):/, ''); if (chunk.msg.match(/SyntaxError: SyntaxError/)) { chunk.msg = chunk.msg.replace('SyntaxError: ', ''); } } else if (chunk.msg.match(/DeprecationWarning/)) { chunk.msg = ''; } } return chunk; }); this._projectRoot = projectRoot; this._getCurrentOpenProjectId = getCurrentOpenProjectId || (() => 1); this._updateLogs = updateLogs; // Optional properties in case the consumer wants to handle updates on // its own, eg: for a progress bar this._onStartBuildBundle = onStartBuildBundle; this._onProgressBuildBundle = onProgressBuildBundle; this._onFinishBuildBundle = onFinishBuildBundle; // Optional function for creating custom code frame snippet // (e.g. with terminal colors) from a syntax error. this._getSnippetForError = getSnippetForError; this._attachLoggerStream(); } _attachLoggerStream() { let projectId = this._getCurrentOpenProjectId(); ProjectUtils().attachLoggerStream(this._projectRoot, { stream: { write: chunk => { if (chunk.tag !== 'metro' && chunk.tag !== 'expo') { return; } else if (this._getCurrentOpenProjectId() !== projectId) { // TODO: We should be confident that we are properly unsubscribing // from the stream rather than doing a defensive check like this. return; } chunk = this._maybeParseMsgJSON(chunk); chunk = this._cleanUpNodeErrors(chunk); if (chunk.tag === 'metro') { this._handleMetroEvent(chunk); } else if (typeof chunk.msg === 'string' && chunk.msg.match(/\w/) && chunk.msg[0] !== '{') { this._enqueueAppendLogChunk(chunk); } } }, type: 'raw' }); } _handleMetroEvent(originalChunk) { const chunk = { ...originalChunk }; let { msg } = chunk; if (typeof msg === 'string') { if (msg.includes('HTTP/1.1') && !_getenv().default.boolish('EXPO_DEBUG', false)) {// Do nothing with this message - we want to filter out network requests logged by Metro. } else { // If Metro crashes for some reason, it may log an error message as a plain string to stderr. this._enqueueAppendLogChunk(chunk); } return; } switch (msg.type) { // Bundle transform events case 'bundle_build_started': case 'bundle_transform_progressed': case 'bundle_build_failed': case 'bundle_build_done': this._handleBundleTransformEvent(chunk); return; case 'initialize_started': chunk._metroEventType = 'METRO_INITIALIZE_STARTED'; chunk.msg = msg.port ? `Starting Metro Bundler on port ${msg.port}.` : 'Starting Metro Bundler.'; break; case 'initialize_done': chunk.msg = `Metro Bundler ready.`; break; case 'initialize_failed': { // SDK <=22 let code = msg.error.code; chunk.msg = code === 'EADDRINUSE' ? `Metro Bundler can't listen on port ${msg.port}. The port is in use.` : `Metro Bundler failed to start. (code: ${code})`; break; } case 'bundling_error': chunk.msg = this._formatModuleResolutionError(msg.error) || this._formatBundlingError(msg.error) || msg; chunk.level = _Logger().default.ERROR; break; case 'transform_cache_reset': chunk.msg = 'Your JavaScript transform cache is empty, rebuilding (this may take a minute).'; break; case 'hmr_client_error': chunk.msg = `A WebSocket client got a connection error. Please reload your device to get HMR working again.`; break; case 'global_cache_disabled': if (msg.reason === 'too_many_errors') { chunk.msg = 'The global cache is now disabled because it has been failing too many times.'; } else if (msg.reason === 'too_many_misses') { chunk.msg = `The global cache is now disabled because it has been missing too many consecutive keys.`; } else { chunk.msg = `The global cache is now disabled. Reason: ${msg.reason}`; } break; case 'worker_stdout_chunk': chunk.msg = this._formatWorkerChunk('stdout', msg.chunk); break; case 'worker_stderr_chunk': chunk.msg = this._formatWorkerChunk('stderr', msg.chunk); break; // Ignored events. case 'dep_graph_loading': case 'dep_graph_loaded': case 'global_cache_error': return; default: chunk.msg = `Unrecognized event: ${JSON.stringify(msg)}`; break; } this._enqueueAppendLogChunk(chunk); } // Any event related to bundle building is handled here _handleNewBundleTransformStarted(chunk) { if (this._bundleBuildChunkID) { return; } this._bundleBuildChunkID = chunk.id; this._bundleBuildStart = new Date(); chunk.msg = 'Building JavaScript bundle'; if (this._onStartBuildBundle) { this._onStartBuildBundle(chunk); } else { this._enqueueAppendLogChunk(chunk); } } _handleUpdateBundleTransformProgress(progressChunk) { const msg = progressChunk.msg; let percentProgress; let bundleComplete = false; if (msg.type === 'bundle_build_done') { percentProgress = 100; bundleComplete = true; if (this._bundleBuildStart) { const duration = new Date().getTime() - this._bundleBuildStart.getTime(); progressChunk.msg = `Building JavaScript bundle: finished in ${duration}ms.`; } else { progressChunk.msg = `Building JavaScript bundle: finished.`; } } else if (msg.type === 'bundle_build_failed') { percentProgress = -1; bundleComplete = true; progressChunk.msg = `Building JavaScript bundle: error`; progressChunk.level = _Logger().default.ERROR; } else if (msg.type === 'bundle_transform_progressed') { percentProgress = Math.floor(msg.transformedFileCount / msg.totalFileCount * 100); progressChunk.msg = `Building JavaScript bundle: ${percentProgress}%`; } else { return; } if (this._bundleBuildChunkID) { progressChunk.id = this._bundleBuildChunkID; } if (this._onProgressBuildBundle) { this._onProgressBuildBundle(percentProgress, this._bundleBuildStart, progressChunk); if (bundleComplete) { if (this._onFinishBuildBundle && this._bundleBuildStart) { const error = msg.type === 'bundle_build_failed' ? 'Build failed' : null; this._onFinishBuildBundle(error, this._bundleBuildStart, new Date(), progressChunk); } this._bundleBuildStart = null; this._bundleBuildChunkID = null; } } else { this._updateLogs(logs => { if (!logs || !logs.length) { return []; } logs.forEach(log => { if (log.id === this._bundleBuildChunkID) { log.msg = progressChunk.msg; } }); if (bundleComplete) { this._bundleBuildChunkID = null; } return [...logs]; }); } } _formatModuleResolutionError(error) { if (!error.message) { return null; } const match = /^Unable to resolve module `(.+?)`/.exec(error.message); const originModulePath = error.originModulePath; if (!match || !originModulePath) { return null; } const moduleName = match[1]; const relativePath = _path().default.relative(this._projectRoot, originModulePath); const DOCS_PAGE_URL = 'https://docs.expo.io/versions/latest/introduction/faq/#can-i-use-nodejs-packages-with-expo'; if (NODE_STDLIB_MODULES.includes(moduleName)) { if (originModulePath.includes('node_modules')) { return `The package at "${relativePath}" attempted to import the Node standard library module "${moduleName}". It failed because React Native does not include the Node standard library. Read more at ${DOCS_PAGE_URL}`; } else { return `You attempted attempted to import the Node standard library module "${moduleName}" from "${relativePath}". It failed because React Native does not include the Node standard library. Read more at ${DOCS_PAGE_URL}`; } } return `Unable to resolve "${moduleName}" from "${relativePath}"`; } _formatBundlingError(error) { let message = error.message; if (!message && Array.isArray(error.errors) && error.errors.length) { message = error.errors[0].description; } if (!message) { return null; } message = _chalk().default.red(message); let snippet = this._getSnippetForError && this._getSnippetForError(error) || error.snippet; if (snippet) { message += `\n${snippet}`; } return message; } _formatWorkerChunk(origin, chunk) { const lines = chunk.split('\n'); if (lines.length >= 1 && lines[lines.length - 1] === '') { lines.splice(lines.length - 1, 1); } return lines.map(line => `transform[${origin}]: ${line}`).join('\n'); } _enqueueAppendLogChunk(chunk) { if (!chunk.shouldHide) { this._logsToAdd.push(chunk); this._enqueueFlushLogsToAdd(); } } _maybeParseMsgJSON(chunk) { try { let parsedMsg = JSON.parse(chunk.msg); chunk.msg = parsedMsg; } catch (e) {// non-JSON message } return chunk; } } exports.default = PackagerLogsStream; const NODE_STDLIB_MODULES = ['assert', 'async_hooks', 'buffer', 'child_process', 'cluster', 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net', 'os', 'path', 'punycode', 'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib']; //# sourceMappingURL=../__sourcemaps__/logs/PackagerLogsStream.js.map