Ctrl K
ComunidadGuías…

scripts/startWeb.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/** Start the live Worker and Rsbuild together, keeping browser-facing URLs independent of the upstream. */
import {$} from 'bun';
import concurrently from 'concurrently';

// The Worker is a separately installed package that the App does not depend on, so it can only be reached by path.
// eslint-disable-next-line import/no-relative-packages
import {API_PROXY_PORT} from '../web/cloudflare-worker/src/developmentAPIProxy';
import checkWebServer from './utils/checkWebServer';
import getWebCommands from './utils/getWebCommands';
import {findWebDevPorts, getDevelopmentConnectOrigins, getWebDevFlags, isWebPortAvailable} from './utils/webDevConfig';
import waitForWebServer from './waitForWebServer';

async function startWeb() {
    // Bun loads .env automatically, preserving explicit shell overrides.
    const isWorkerInstalled = await Bun.file('web/cloudflare-worker/node_modules/wrangler/bin/wrangler.js').exists();
    const {isWorkerEnabled, isWorkerMissing, isProxyEnabled, shouldOpenBrowser} = getWebDevFlags(Bun.env, isWorkerInstalled);
    if (isWorkerMissing) {
        console.warn('Cloudflare Worker tooling is not installed, so serving Rsbuild directly without the Worker. Run npm install (it skips the Worker when CI is set).');
    }
    const {publicPort, internalPort} = findWebDevPorts(Bun.env, isWorkerEnabled, isWebPortAvailable);
    const shouldStartProxy = isProxyEnabled && isWebPortAvailable(API_PROXY_PORT, '::');
    if (isProxyEnabled && !shouldStartProxy) {
        console.log(`Reusing the API proxy already on port ${API_PROXY_PORT}, e.g. from another worktree's session. API requests stop working if that session stops.`);
    }
    for (const file of ['key.pem', 'certificate.pem']) {
        if (!(await Bun.file(`config/rsbuild/${file}`).exists())) {
            throw new Error('Missing local HTTPS certificate. Run npm run setup-https first.');
        }
    }
    const origin = `https://dev.new.expensify.com:${publicPort}`;
    const commands = getWebCommands({
        root: process.cwd(),
        isWorkerEnabled,
        isProxyEnabled,
        shouldStartProxy,
        publicPort,
        internalPort,
        connectOrigins: getDevelopmentConnectOrigins(Bun.env),
    });
    const controller = new AbortController();
    const {commands: children, result} = concurrently(commands, {killOthersOn: ['success', 'failure'], killTimeout: 3000});
    const stop = () => {
        controller.abort();
        for (const child of children) {
            child.kill('SIGTERM');
        }
    };
    process.once('SIGINT', stop);
    process.once('SIGTERM', stop);
    // Verify the browser-facing listener and certificate, not just the internal compiler's listener.
    const readiness = (async () => {
        const isReady = await waitForWebServer((signal) => checkWebServer(origin, isWorkerEnabled, signal), controller.signal, {
            slowAfter: 180_000,
            onSlow: () => console.warn(`Still waiting for ${origin}/. Check the dev server output. If it compiled, check that its certificate is trusted (npm run setup-https).`),
        });
        if (!isReady) {
            return;
        }
        console.log(`Web app ready at ${origin}/ (${isWorkerEnabled ? 'Cloudflare Worker' : 'direct Rsbuild'})`);
        if (shouldOpenBrowser) {
            const browserCommands: Partial<Record<NodeJS.Platform, string>> = {darwin: 'open', win32: 'cmd'};
            const command = browserCommands[process.platform] ?? 'xdg-open';
            const args = process.platform === 'win32' ? ['/c', 'start', '', `${origin}/`] : [`${origin}/`];
            $`${command} ${args}`.quiet().catch((error: unknown) => {
                console.error(`Open ${origin}/ in your browser:`, error);
            });
        }
    })();
    try {
        await Promise.race([result, readiness]);
        await result;
    } finally {
        stop();
        await readiness.catch(() => {});
        process.removeListener('SIGINT', stop);
        process.removeListener('SIGTERM', stop);
    }
}

startWeb().catch((error: unknown) => {
    console.error(error);
    process.exitCode = 1;
});