UNPKG

@alithanar/react-automation-profiler

Version:

Automated React profiling and data visualization using React's Profiler API, Puppeteer, and D3.

162 lines 6.54 kB
#!/usr/bin/env node --no-warnings "use strict"; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const browser_sync_1 = __importDefault(require("browser-sync")); const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); const yargs_1 = __importDefault(require("yargs")); const automation_1 = __importDefault(require("./automation/automation")); const util_1 = require("./utils/util"); const helpers_1 = require("yargs/helpers"); const AutomationResultsStorage_1 = require("./automation/AutomationResultsStorage"); const interfaces_1 = require("./interfaces"); const path_2 = require("path"); console.log(` █▀█ ▄▀█ █▀█ █▀▄ █▀█ █▀▀ \x1b[1;32mreact automation profiler\x1b[37m `); const options = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv)) .usage(`Usage: --averageOf <averageOf> --changeInterval <changeInterval> \ --includeMount <includeMount> --page <page> --port <port> --watch <watch>`) .option('averageOf', { describe: 'run each flow n number of times and average out the metrics', type: 'number', }) .option('changeInterval', { describe: 'number of changes before automation is rerun', type: 'number', }) .option('includeMount', { describe: 'includes the initial mount render', type: 'boolean', }) .option('page', { describe: 'page to be tested', type: 'string', demandOption: true, }) .option('port', { describe: 'port to be used for server', type: 'number', }) .option('watch', { describe: 'generate charts on every new build', type: 'boolean' || 'string', }) .option('output', { describe: 'choose the desired output. Acceptable values: [chart, json]', type: 'string', }) .option('headless', { describe: 'determines if chromium browser window should be visible', type: 'boolean', }).argv; const { averageOf = 1, changeInterval = 1, includeMount = false, page, port = 1235, watch = false, headless = true, output = interfaces_1.OutputType.CHART, } = options; const cwd = path_1.default.resolve(); const scriptPath = (0, path_2.resolve)('./lib/bin.js'); const packagePath = `${scriptPath.slice(0, scriptPath.lastIndexOf('/'))}`; const serverPath = `http://localhost:${port + 1}`; let changeCount = 0; let versionCount = 0; let isServerReady = false; let timer; const resultsStorage = new AutomationResultsStorage_1.AutomationResultsStorage(); function checkShouldAutomate() { clearTimeout(timer); timer = setTimeout(async () => { changeCount++; if (changeCount >= changeInterval) { changeCount = 0; await handleAutomation(); browser_sync_1.default.reload(); } // will re-automate after 10 seconds to give time for the host project // to rebuild after changes }, 10000); } function getStopMessage(output) { return output === interfaces_1.OutputType.CHART ? `Displaying ${versionCount++ ? `${versionCount} versions of ` : ''}charts at: \x1b[1;32mhttp://localhost:${port}\x1b[37m` : 'Automation finished'; } async function handleAutomation() { for (let automationCount = 1; automationCount <= averageOf; automationCount++) { (0, util_1.printMessage)("AUTOMATION_START" /* AUTOMATION_START */); const automationProps = { automationCount, averageOf, cwd, includeMount, isServerReady, packagePath, serverPort: port + 1, url: page, headless, output, }; await (0, automation_1.default)(automationProps, resultsStorage); (0, util_1.printMessage)("AUTOMATION_STOP" /* AUTOMATION_STOP */, { log: getStopMessage(output) }); if (!isServerReady && automationCount === averageOf) isServerReady = true; } } function setupProxy() { browser_sync_1.default.init({ browser: 'google chrome', logLevel: 'silent', notify: false, open: true, port, proxy: serverPath, reloadOnRestart: true, }); } // run /***********************/ (async () => { var e_1, _a; try { await handleAutomation(); } catch (error) { (0, util_1.printMessage)("AUTOMATION_STOP" /* AUTOMATION_STOP */, { e: error }); process.exit(); } if (output === interfaces_1.OutputType.CHART) { setupProxy(); if (watch) { const watchDir = typeof watch === 'string' ? `${cwd}/${watch}` : cwd; const events = promises_1.default.watch(watchDir, { recursive: true } // node types are saying that fs.watch returns AsyncIterable<string>, but // it's actually AsyncIterable<{ eventType: string; filename: string }>. // Have to cast as unknown first to get around this. ); try { for (var events_1 = __asyncValues(events), events_1_1; events_1_1 = await events_1.next(), !events_1_1.done;) { const { eventType, filename } = events_1_1.value; if (eventType === 'change' && !filename.startsWith('node_modules')) { checkShouldAutomate(); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (events_1_1 && !events_1_1.done && (_a = events_1.return)) await _a.call(events_1); } finally { if (e_1) throw e_1.error; } } } } })(); //# sourceMappingURL=bin.js.map