@trifrost/core
Version:
Blazingly fast, runtime-agnostic server framework for modern edge and node environments
98 lines (97 loc) • 3.59 kB
JavaScript
;
/// <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;