UNPKG

@trifrost/core

Version:

Blazingly fast, runtime-agnostic server framework for modern edge and node environments

98 lines (97 loc) 3.59 kB
"use strict"; /// <reference types="bun-types" /> Object.defineProperty(exports, "__esModule", { value: true }); exports.BunRuntime = void 0; const number_1 = require("@valkyriestudios/utils/number"); const Logger_1 = require("../../modules/Logger"); const Context_1 = require("./Context"); const Generic_1 = require("../../utils/Generic"); class BunRuntime { /* Bun Http server instance */ #server = null; /* Global logger instance when runtime has started */ #logger = null; /* Incoming handler which is to be called by the runtime when an incoming request happens */ #onIncoming = null; /** * MARK: Runtime Implementation */ exports = null; get name() { return 'Bun'; } get version() { return Bun.version || null; } async boot(opts) { let serve; let file; try { ({ serve, file } = await import('bun')); } catch { throw new Error('BunRuntime@boot: Failed to load required modules'); } /* Reject if server is already set */ if (this.#server !== null) { throw new Error('BunRuntime@boot: Server already listening'); } /* Set onIncoming handler */ this.#onIncoming = opts.onIncoming; /* Set logger instance */ this.#logger = opts.logger; /* Specific APIs used by the context */ const apis = { file }; /** * Context config. * Take Note: Given that we don't know whether or not bun will run standalone or * behind a proxy we default trustProxy to false here. */ const cfg = { ...opts.cfg, env: { ...process.env, ...opts.cfg.env }, }; /* Determine trust proxy */ cfg.trustProxy = (0, Generic_1.determineTrustProxy)(cfg.env, false); /* Construct options for serve */ const serveOpts = { port: (0, Generic_1.determinePort)(cfg.env, cfg.port), hostname: (0, Generic_1.determineHost)(cfg.env), fetch: async (req) => { const ctx = new Context_1.BunContext(cfg, opts.logger, apis, req); try { await this.#onIncoming(ctx); if (!ctx.response) throw new Error('BunContext@onIncoming: Handler did not respond'); return ctx.response; } catch (err) { opts.logger.error(err); return new Response('Internal Server Error', { status: 500 }); } }, }; /* Use timeout as idleTimeout if configured */ if ((0, number_1.isInt)(cfg.timeout)) { const timeout_s = cfg.timeout / 1000; /* Ensure timeout stays within 255 seconds as bun limitation */ serveOpts.idleTimeout = (0, number_1.isIntBetween)(timeout_s, 0, 255) ? timeout_s : 255; } /* Bun serve */ this.#server = serve(serveOpts); this.#logger.debug(`BunRuntime@boot: Listening on port ${opts.cfg.port}`); } defaultExporter(env) { return (0, Generic_1.isDevMode)(env) ? new Logger_1.ConsoleExporter() : new Logger_1.ConsoleExporter({ include: ['trace_id'] }); } async shutdown() { if (!this.#server) return; this.#logger.debug('BunRuntime@shutdown'); this.#server.stop(); this.#server = null; this.#onIncoming = null; this.#logger = null; } } exports.BunRuntime = BunRuntime;