UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

204 lines 7.18 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var serve_exports = {}; __export(serve_exports, { serve: () => serve }); module.exports = __toCommonJS(serve_exports); var import_polyfills_server = require("./polyfills-server.cjs"); var import_fs_extra = __toESM(require("fs-extra"), 1); var import_setServerGlobals = require("./server/setServerGlobals.cjs"); var import_setupBuildOptions = require("./server/setupBuildOptions.cjs"); var import_ensureExists = require("./utils/ensureExists.cjs"); process.on("uncaughtException", err => { console.error(`[one] Uncaught exception`, err?.stack || err); }); async function serve(args = {}) { if (args.cluster) { const { cpus, platform } = await import("node:os"); const numWorkers = typeof args.cluster === "number" ? args.cluster : cpus().length; const isBun = typeof process.versions.bun !== "undefined"; const canReusePort = !["win32", "darwin"].includes(platform()) && (isBun || (() => { const [major, minor] = process.versions.node.split(".").map(Number); return major > 22 || major === 22 && minor >= 12 || major >= 23; })()); if (canReusePort) { return await serveWithReusePort(args, numWorkers); } else if (!isBun) { return await serveWithCluster(args, numWorkers); } else { console.warn(`[one] cluster mode not supported on ${platform()} with bun, running single process`); return await startWorker(args); } } return await startWorker(args); } async function serveWithReusePort(args, numWorkers) { const { fork } = await import("node:child_process"); console.info(`[one] cluster: starting ${numWorkers} workers (SO_REUSEPORT)`); const workers = []; let recentCrashes = 0; let lastCrashTime = 0; function spawnWorker() { const child = fork(process.argv[1], process.argv.slice(2).filter(a => !a.startsWith("--cluster")), { env: { ...process.env, ONE_CLUSTER_WORKER: "1" }, stdio: "inherit" }); workers.push(child); child.on("exit", (code, signal) => { const idx = workers.indexOf(child); if (idx >= 0) workers.splice(idx, 1); if (code === 0 || signal === "SIGTERM" || signal === "SIGINT") return; const now = Date.now(); if (now - lastCrashTime < 5e3) { recentCrashes++; } else { recentCrashes = 1; } lastCrashTime = now; if (recentCrashes > numWorkers * 2) { console.error(`[one] too many worker crashes, stopping`); process.exit(1); } console.error(`[one] worker ${child.pid} died (code ${code}, signal ${signal}), restarting`); setTimeout(spawnWorker, Math.min(recentCrashes * 500, 5e3)); }); } for (let i = 0; i < numWorkers; i++) { spawnWorker(); } const shutdown = () => { for (const w of workers) { w.kill("SIGTERM"); } setTimeout(() => process.exit(0), 5e3); }; process.on("SIGINT", shutdown); process.on("SIGTERM", shutdown); await new Promise(() => {}); } async function serveWithCluster(args, numWorkers) { const cluster = await import("node:cluster"); if (cluster.default.isPrimary) { console.info(`[one] cluster: starting ${numWorkers} workers (IPC)`); for (let i = 0; i < numWorkers; i++) { cluster.default.fork(); } let recentCrashes = 0; let lastCrashTime = 0; cluster.default.on("exit", (worker, code, signal) => { if (code === 0 || signal === "SIGTERM" || signal === "SIGINT") return; const now = Date.now(); if (now - lastCrashTime < 5e3) { recentCrashes++; } else { recentCrashes = 1; } lastCrashTime = now; if (recentCrashes > numWorkers * 2) { console.error(`[one] too many worker crashes, stopping`); process.exit(1); } console.error(`[one] worker ${worker.process.pid} died (code ${code}, signal ${signal}), restarting`); setTimeout(() => cluster.default.fork(), Math.min(recentCrashes * 500, 5e3)); }); const shutdown = () => { for (const id in cluster.default.workers) { cluster.default.workers[id]?.process.kill("SIGTERM"); } setTimeout(() => process.exit(0), 5e3); }; process.on("SIGINT", shutdown); process.on("SIGTERM", shutdown); return; } return await startWorker(args); } async function startWorker(args) { const outDir = args?.outDir || (import_fs_extra.default.existsSync("buildInfo.json") ? "." : null) || "dist"; const buildInfo = await import_fs_extra.default.readJSON(`${outDir}/buildInfo.json`); const { oneOptions } = buildInfo; (0, import_setServerGlobals.setServerGlobals)(); (0, import_setupBuildOptions.setupBuildInfo)(buildInfo); (0, import_ensureExists.ensureExists)(oneOptions); const { labelProcess } = await import("./cli/label-process"); const { removeUndefined } = await import("./utils/removeUndefined"); const { loadEnv, serve: vxrnServe, serveStaticAssets, compileCacheRules } = await import("vxrn/serve"); const { oneServe } = await import("./server/oneServe"); labelProcess("serve"); if (args?.loadEnv) { await loadEnv("production"); } const cacheRules = oneOptions.server?.cacheControl ? compileCacheRules(oneOptions.server.cacheControl) : void 0; return await vxrnServe({ outDir: buildInfo.outDir || outDir, app: args?.app, ...oneOptions.server, ...removeUndefined({ port: args?.port ? +args.port : void 0, host: args?.host, compress: args?.compress }), async beforeRegisterRoutes(options, app) { await oneServe(oneOptions, buildInfo, app, { serveStaticAssets: ctx => serveStaticAssets({ ...ctx, cacheRules }) }); }, async afterRegisterRoutes(options, app) {} }); }