UNPKG

@nxextensions/firebase

Version:

An Nx plugin for firebase applications that would like to run the emulators in conjunction with their app

176 lines 6.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.startEmulators = startEmulators; const devkit_1 = require("@nx/devkit"); const process = require("node:process"); const fileutils_1 = require("nx/src/utils/fileutils"); const request_1 = require("./request"); const child_process_1 = require("child_process"); const es = require("event-stream"); const fs_1 = require("fs"); const path_1 = require("path"); const chalk = require("chalk"); async function startEmulators(command, context, exportPath) { if (await isServerUp(command, context)) { return; } const killEmulators = runCommand(command, context, exportPath); await waitForServer(command, context); return killEmulators; } function isServerUp(command, context) { const parts = command.split('--'); const onlyPart = parts.filter((p) => p.includes('only'))[0]; const firstPort = getFirstEmulatorPort(context, onlyPart); const url = `http://localhost:${firstPort}`; return new Promise((res) => { return (0, request_1.default)(url, () => { res(true); }, () => { res(false); }); }); } function getFirstEmulatorPort(context, only) { const projectRoot = (0, devkit_1.joinPathFragments)(context.cwd, context.projectsConfigurations.projects[context.projectName].root); let path = 'firebase.json'; if (!(0, fs_1.existsSync)('firebase.json')) { path = (0, devkit_1.joinPathFragments)(projectRoot, path); if (!(0, fs_1.existsSync)((0, devkit_1.joinPathFragments)(projectRoot, 'nx-firebase.json'))) { const message = chalk.bgKeyword('orange')("The process has detected that you are running a version of this plugin that does not have the nx-firebase.json file present. This will not be supported in v2. Please run 'nx migrate @nxextensions/firebase@v1.3.0' to fix this issue"); process.stdout.write(message); } } const firebaseConfig = (0, fileutils_1.readJsonFile)(path); if (!(firebaseConfig === null || firebaseConfig === void 0 ? void 0 : firebaseConfig.emulators)) { throw new Error(`firebase.json does not contain the necessary emulators configuration`); } let port; Object.keys(firebaseConfig.emulators).forEach((emulator) => { if (!port && firebaseConfig.emulators[emulator].port) { if ((only && only.includes(emulator)) || !only) { port = firebaseConfig.emulators[emulator].port; } } }); return port; } function runCommand(command, context, exportPath) { var _a, _b; let cwd = process.cwd(); if (!(0, fs_1.existsSync)((0, path_1.join)(cwd, 'firebase.json'))) { cwd = (0, devkit_1.joinPathFragments)(cwd, context.projectsConfigurations.projects[context.projectName].root); } const cp = (0, child_process_1.exec)(command, { cwd }); (_a = cp.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => { process.stdout.write(data); }); (_b = cp.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => { process.stderr.write(data); }); return async () => { if (process.platform === 'win32') { if (exportPath) { (0, child_process_1.execSync)(`firebase emulators:export ${exportPath}`); } await listChildProcessPID(cp.pid, (pids, err) => { if (err) { throw err; } pids.forEach((pid) => { (0, child_process_1.exec)(`taskkill /f /pid ${pid.PID}`); }); }); } else { process.kill(-cp.pid, 'SIGINT'); } }; } function waitForServer(command, context) { const port = getFirstEmulatorPort(context, command); return new Promise((res, rej) => { let pollTimeout; const timeout = setTimeout(() => { clearTimeout(pollTimeout); rej(); }, 120000); function pollForServer() { void (0, request_1.default)(`http://localhost:${port}`, () => { clearTimeout(timeout); res(); }, () => { pollTimeout = setTimeout(pollForServer, 100); }); } pollForServer(); }); } function listChildProcessPID(pid, callback) { return new Promise((res, rej) => { let headers = null; if (typeof callback !== 'function') { throw new Error('listChildProcessPID: callback must be a function'); } if (typeof pid === 'number') { pid = pid.toString(); } let processLister; if (process.platform === 'win32') { processLister = (0, child_process_1.exec)('wmic.exe PROCESS GET Name,ProcessId,ParentProcessId,Status'); } else { processLister = (0, child_process_1.exec)('ps -A -o ppid,pid,stat,comm'); } processLister.on('exit', (code) => { if (code !== 0) { rej(new Error('wmic.exe exited with code ' + code)); } else { res(); } }); es.connect(processLister.stdout, es.split(), es.map((line, cb) => { const columns = line.trim().split(/\s+/); if (!headers) { headers = columns; headers = headers.map(normalizeHeaders); return cb(); } const row = {}; const h = headers.slice(); while (h.length) { row[h.shift()] = h.length ? columns.shift() : columns.join(' '); } return cb(null, row); }), es.writeArray((err, ps) => { const parents = {}, children = []; parents[pid] = true; ps.forEach((p) => { if (parents[p.PPID]) { parents[p.PID] = true; children.push(p); } }); callback(children, null); })).on('error', (err) => { callback([], err); }); }); } function normalizeHeaders(str) { switch (str) { case 'Name': case 'COMM': return 'COMMAND'; case 'ParentProcessId': return 'PPID'; case 'ProcessId': return 'PID'; case 'Status': return 'STAT'; default: return str; } } //# sourceMappingURL=firebase.js.map