@trifrost/core
Version:
Blazingly fast, runtime-agnostic server framework for modern edge and node environments
74 lines (73 loc) • 3.07 kB
JavaScript
import { ConsoleExporter } from '../../modules/Logger';
import { NodeContext } from './Context';
import { determinePort, determineTrustProxy, isDevMode } from '../../utils/Generic';
export class NodeRuntime {
/* Node 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 'Node';
}
get version() {
return process.version || null;
}
async boot(opts) {
const { Readable } = await import('node:stream');
const { createServer } = await import('node:http');
const { statSync, createReadStream } = await import('node:fs');
const { pipeline } = await import('node:stream/promises');
return new Promise((resolve, reject) => {
/* Reject if server is already set */
if (this.#server !== null) {
return reject(new Error('NodeRuntime@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 = { statSync, createReadStream, pipeline, Readable };
/**
* Context config
* Take Note: Given that we don't know whether or not node 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 = determineTrustProxy(cfg.env, false);
/* Create new server instance */
this.#server = createServer(async (req, res) => this.#onIncoming(new NodeContext(cfg, opts.logger, apis, req, res)));
/* Listen on the provided port, resolve if succeeds, reject if fails */
this.#server.listen(determinePort(cfg.env, opts.cfg.port), () => {
this.#logger.debug(`NodeRuntime@boot: Listening on port ${opts.cfg.port}`);
return resolve();
}).on('error', () => {
this.#server = null;
this.#onIncoming = null;
return reject(new Error(`NodeRuntime@boot: Failed to listen on port ${opts.cfg.port}`));
});
});
}
defaultExporter(env) {
return isDevMode(env) ? new ConsoleExporter() : new ConsoleExporter({ include: ['trace_id'] });
}
async shutdown() {
if (!this.#server)
return;
this.#logger.debug('NodeRuntime@shutdown');
await new Promise(resolve => this.#server.close(() => resolve()));
this.#server = null;
this.#onIncoming = null;
this.#logger = null;
}
}