ufiber
Version:
Next-gen webserver for node-js developer
128 lines (126 loc) • 4.02 kB
JavaScript
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
const require_tools = require('./utils/tools.cjs');
const require_consts = require('./consts.cjs');
const require_context = require('./http/context.cjs');
require('./http/index.cjs');
const require_compose = require('./router/compose.cjs');
const require_index$1 = require('./router/index.cjs');
let uws = require("../uws");
uws = require_rolldown_runtime.__toESM(uws);
let node_path = require("node:path");
node_path = require_rolldown_runtime.__toESM(node_path);
//#region src/ufiber.ts
/**
* The Fiber class extends the functionality of the Router class.
* It sets up routing and allows for custom options to be passed.
*/
var Fiber = class extends require_index$1.Router {
uws;
#name;
isSSL;
#methods;
bodyLimit;
/**
* Creates an instance of the Fiber class.
*
* @param options - Optional configuration options for the Fiber instance.
*/
constructor(options = Object.create(null)) {
super();
this.#name = options.name || "Fiber";
this.#methods = options.methods;
this.bodyLimit = require_tools.parseBytes(options.bodyLimit || "16MB");
const opts = options.uwsOptions ?? {};
if (opts.key_file_name && opts.cert_file_name) {
this.uws = uws.default.SSLApp(opts);
this.isSSL = true;
} else {
this.uws = uws.default.App(opts);
this.isSSL = false;
}
}
/**
* Add WebSocket support
*
* @param pattern - URL pattern for WebSocket endpoint
* @param behavior - WebSocket behavior configuration
* @returns this for chaining
*
* @example
* ```ts
* app.ws('/chat', {
* message: (ws, message, opCode) => {
* ws.send(message);
* },
* open: (ws) => {
* console.log('WebSocket connected');
* }
* });
* ```
*/
ws(pattern, behavior) {
this.uws.ws(pattern, behavior);
return this;
}
#dispatch = (res, req) => {
const ctx = new require_context.Context({
req,
res,
isSSL: this.isSSL,
appName: this.#name,
bodyLimit: this.bodyLimit,
methods: this.#methods
});
const matchResult = this.router.match(ctx.method === "HEAD" ? "GET" : ctx.method, ctx.path);
ctx[require_consts.kMatch] = matchResult;
if (!matchResult) return this[require_index$1.kNotFound](ctx);
if (matchResult[0].length === 1) {
try {
const result$1 = matchResult[0][0][0][0](ctx, async () => await this[require_index$1.kNotFound](ctx));
if (require_tools.isPromise(result$1)) result$1.catch((err) => this[require_index$1.kErrorHandler](err, ctx));
} catch (err) {
this[require_index$1.kErrorHandler](err, ctx);
}
return;
}
const result = require_compose.compose(matchResult[0], {
onError: this[require_index$1.kErrorHandler],
onNotFound: this[require_index$1.kNotFound]
})(ctx);
if (require_tools.isPromise(result)) result.catch((err) => this[require_index$1.kErrorHandler](err, ctx));
};
listen(...args) {
this.uws.any("/*", this.#dispatch);
let port = 0;
let host;
let cb;
if (typeof args[0] === "function") cb = args[0];
else if (typeof args[1] === "function") {
port = args[0];
cb = args[1];
} else [port, host, cb] = args;
const onListen = (socket) => {
if (!socket) throw new Error(`Failed to listen on ${port}. No permission or address in use.`);
let address;
if (typeof port === "string" && isNaN(Number(port))) {
const normalizedPath = port.startsWith("/") || port.startsWith("./") ? port : `./${port}`;
address = node_path.default.resolve(normalizedPath);
} else address = `${this.isSSL ? "https" : "http"}://${host ?? "0.0.0.0"}:${port}`;
cb?.(address);
};
if (typeof port === "string" && isNaN(Number(port))) this.uws.listen_unix(onListen, port);
else {
const numericPort = Number(port);
if (host) this.uws.listen(host, numericPort, onListen);
else this.uws.listen(numericPort, onListen);
}
const shutdown = () => {
this.uws.close();
process.exit(0);
};
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
}
};
//#endregion
exports.Fiber = Fiber;