Update app and tooling

This commit is contained in:
Lawrence Chen 2026-01-29 17:36:26 -08:00
parent 3046531bdd
commit e620ec7349
4950 changed files with 2975120 additions and 10 deletions

View file

@ -0,0 +1,13 @@
//#region src/_middleware.ts
function wrapFetch(server) {
const fetchHandler = server.options.fetch;
const middleware = server.options.middleware || [];
return middleware.length === 0 ? fetchHandler : (request) => callMiddleware(request, fetchHandler, middleware, 0);
}
function callMiddleware(request, fetchHandler, middleware, index) {
if (index === middleware.length) return fetchHandler(request);
return middleware[index](request, () => callMiddleware(request, fetchHandler, middleware, index + 1));
}
//#endregion
export { wrapFetch };

16
node_modules/srvx/dist/_chunks/_plugins-DOhVIkXu.mjs generated vendored Normal file
View file

@ -0,0 +1,16 @@
//#region src/_plugins.ts
const errorPlugin = (server) => {
const errorHandler = server.options.error;
if (!errorHandler) return;
server.options.middleware.unshift((_req, next) => {
try {
const res = next();
return res instanceof Promise ? res.catch((error) => errorHandler(error)) : res;
} catch (error) {
return errorHandler(error);
}
});
};
//#endregion
export { errorPlugin };

91
node_modules/srvx/dist/_chunks/_url-CdE4ce6F.mjs generated vendored Normal file
View file

@ -0,0 +1,91 @@
//#region src/_url.ts
/**
* Wrapper for URL with fast path access to `.pathname` and `.search` props.
*
* **NOTE:** It is assumed that the input URL is already ecoded and formatted from an HTTP request and contains no hash.
*
* **NOTE:** Triggering the setters or getters on other props will deoptimize to full URL parsing.
*/
const FastURL = /* @__PURE__ */ (() => {
const FastURL$1 = class URL {
#originalURL;
#parsedURL;
_pathname;
_urlqindex;
_query;
_search;
constructor(url) {
this.#originalURL = url;
}
get _url() {
if (!this.#parsedURL) this.#parsedURL = new globalThis.URL(this.#originalURL);
return this.#parsedURL;
}
toString() {
return this._url.toString();
}
toJSON() {
return this.toString();
}
get pathname() {
if (this.#parsedURL) return this.#parsedURL.pathname;
if (this._pathname === void 0) {
const url = this.#originalURL;
const protoIndex = url.indexOf("://");
if (protoIndex === -1) return this._url.pathname;
const pIndex = url.indexOf("/", protoIndex + 4);
if (pIndex === -1) return this._url.pathname;
const qIndex = this._urlqindex = url.indexOf("?", pIndex);
this._pathname = url.slice(pIndex, qIndex === -1 ? void 0 : qIndex);
}
return this._pathname;
}
set pathname(value) {
this._pathname = void 0;
this._url.pathname = value;
}
get searchParams() {
if (this.#parsedURL) return this.#parsedURL.searchParams;
if (!this._query) this._query = new URLSearchParams(this.search);
return this._query;
}
get search() {
if (this.#parsedURL) return this.#parsedURL.search;
if (this._search === void 0) {
const qIndex = this._urlqindex;
if (qIndex === -1 || qIndex === this.#originalURL.length - 1) this._search = "";
else this._search = qIndex === void 0 ? this._url.search : this.#originalURL.slice(qIndex);
}
return this._search;
}
set search(value) {
this._search = void 0;
this._query = void 0;
this._url.search = value;
}
};
const slowProps = [
"hash",
"host",
"hostname",
"href",
"origin",
"password",
"port",
"protocol",
"username"
];
for (const prop of slowProps) Object.defineProperty(FastURL$1.prototype, prop, {
get() {
return this._url[prop];
},
set(value) {
this._url[prop] = value;
}
});
Object.setPrototypeOf(FastURL$1, globalThis.URL);
return FastURL$1;
})();
//#endregion
export { FastURL as FastURL$1 };

13
node_modules/srvx/dist/_chunks/_url-D8u5OAto.d.mts generated vendored Normal file
View file

@ -0,0 +1,13 @@
//#region src/_url.d.ts
/**
* Wrapper for URL with fast path access to `.pathname` and `.search` props.
*
* **NOTE:** It is assumed that the input URL is already ecoded and formatted from an HTTP request and contains no hash.
*
* **NOTE:** Triggering the setters or getters on other props will deoptimize to full URL parsing.
*/
declare const FastURL: {
new (url: string): URL;
};
//#endregion
export { FastURL as FastURL$2 };

70
node_modules/srvx/dist/_chunks/_utils-DRF_4b_y.mjs generated vendored Normal file
View file

@ -0,0 +1,70 @@
//#region src/_utils.ts
function resolvePortAndHost(opts) {
const _port = opts.port ?? globalThis.process?.env.PORT ?? 3e3;
const port = typeof _port === "number" ? _port : Number.parseInt(_port, 10);
const hostname = opts.hostname ?? globalThis.process?.env.HOST;
return {
port,
hostname
};
}
function fmtURL(host, port, secure) {
if (!host || !port) return void 0;
if (host.includes(":")) host = `[${host}]`;
return `http${secure ? "s" : ""}://${host}:${port}/`;
}
function printListening(opts, url) {
if (!url || (opts.silent ?? globalThis.process?.env?.TEST)) return;
const _url = new URL(url);
const allInterfaces = _url.hostname === "[::]" || _url.hostname === "0.0.0.0";
if (allInterfaces) {
_url.hostname = "localhost";
url = _url.href;
}
let listeningOn = `➜ Listening on:`;
let additionalInfo = allInterfaces ? " (all interfaces)" : "";
if (globalThis.process.stdout?.isTTY) {
listeningOn = `\u001B[32m${listeningOn}\u001B[0m`;
url = `\u001B[36m${url}\u001B[0m`;
additionalInfo = `\u001B[2m${additionalInfo}\u001B[0m`;
}
console.log(`${listeningOn} ${url}${additionalInfo}`);
}
function resolveTLSOptions(opts) {
if (!opts.tls || opts.protocol === "http") return;
const cert = resolveCertOrKey(opts.tls.cert);
const key = resolveCertOrKey(opts.tls.key);
if (!cert && !key) {
if (opts.protocol === "https") throw new TypeError("TLS `cert` and `key` must be provided for `https` protocol.");
return;
}
if (!cert || !key) throw new TypeError("TLS `cert` and `key` must be provided together.");
return {
cert,
key,
passphrase: opts.tls.passphrase
};
}
function resolveCertOrKey(value) {
if (!value) return;
if (typeof value !== "string") throw new TypeError("TLS certificate and key must be strings in PEM format or file paths.");
if (value.startsWith("-----BEGIN ")) return value;
const { readFileSync } = process.getBuiltinModule("node:fs");
return readFileSync(value, "utf8");
}
function createWaitUntil() {
const promises = new Set();
return {
waitUntil: (promise) => {
promises.add(promise.catch(console.error).finally(() => {
promises.delete(promise);
}));
},
wait: () => {
return Promise.all(promises);
}
};
}
//#endregion
export { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions };

31
node_modules/srvx/dist/_chunks/_utils.cli-B2YzwlOv.mjs generated vendored Normal file
View file

@ -0,0 +1,31 @@
//#region src/_utils.cli.ts
const noColor = globalThis.process?.env?.NO_COLOR === "1" || globalThis.process?.env?.TERM === "dumb";
const resets = {
1: 22,
31: 39,
32: 39,
33: 39,
34: 39,
35: 39,
36: 39,
90: 39
};
const _c = (c) => (text) => {
if (noColor) return text;
const off = resets[c] ?? 0;
return `\u001B[${c}m${text}\u001B[${off}m`;
};
const Colors = {
bold: _c(1),
red: _c(31),
green: _c(32),
yellow: _c(33),
blue: _c(34),
magenta: _c(35),
cyan: _c(36),
gray: _c(90),
url: (title, url) => noColor ? `[${title}](${url})` : `\u001B]8;;${url}\u001B\\${title}\u001B]8;;\u001B\\`
};
//#endregion
export { Colors };

43
node_modules/srvx/dist/_chunks/call-LB9MY5Dv.mjs generated vendored Normal file
View file

@ -0,0 +1,43 @@
import { NodeResponse, NodeResponseHeaders } from "./response-6LJL3Qlz.mjs";
//#region src/adapters/_node/call.ts
function callNodeHandler(handler, req) {
const isMiddleware = handler.length > 2;
const nodeCtx = req.runtime?.node;
if (!nodeCtx || !nodeCtx.req || !nodeCtx.res) throw new Error("Node.js runtime context is not available.");
const { req: nodeReq, res: nodeRes } = nodeCtx;
let _headers;
const webRes = new NodeResponse(void 0, {
get status() {
return nodeRes.statusCode;
},
get statusText() {
return nodeRes.statusMessage;
},
get headers() {
if (!_headers) _headers = new NodeResponseHeaders(nodeCtx);
return _headers;
}
});
return new Promise((resolve, reject) => {
nodeRes.once("close", () => resolve(webRes));
nodeRes.once("finish", () => resolve(webRes));
nodeRes.once("error", (error) => reject(error));
let streamPromise;
nodeRes.once("pipe", (stream) => {
streamPromise = new Promise((resolve$1) => {
stream.once("end", () => resolve$1(webRes));
stream.once("error", (error) => reject(error));
});
});
try {
if (isMiddleware) Promise.resolve(handler(nodeReq, nodeRes, (error) => error ? reject(error) : streamPromise || resolve(webRes))).catch((error) => reject(error));
else Promise.resolve(handler(nodeReq, nodeRes)).then(() => streamPromise || webRes);
} catch (error) {
reject(error);
}
});
}
//#endregion
export { callNodeHandler };

293
node_modules/srvx/dist/_chunks/response-6LJL3Qlz.mjs generated vendored Normal file
View file

@ -0,0 +1,293 @@
import { splitSetCookieString } from "cookie-es";
//#region src/adapters/_node/_common.ts
const kNodeInspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
function inheritProps(target, source, sourceKey) {
for (const key of Object.getOwnPropertyNames(source)) {
if (key in target) continue;
const desc = Object.getOwnPropertyDescriptor(source, key);
if (desc.get) Object.defineProperty(target, key, {
...desc,
get() {
return this[sourceKey][key];
}
});
else if (typeof desc.value === "function") Object.defineProperty(target, key, {
...desc,
value(...args) {
return this[sourceKey][key](...args);
}
});
else Object.defineProperty(target, key, desc);
}
}
//#endregion
//#region src/adapters/_node/headers.ts
const NodeRequestHeaders = /* @__PURE__ */ (() => {
const _Headers = class Headers$1 {
_node;
constructor(nodeCtx) {
this._node = nodeCtx;
}
append(name, value) {
name = validateHeader(name);
const _headers = this._node.req.headers;
const _current = _headers[name];
if (_current) if (Array.isArray(_current)) _current.push(value);
else _headers[name] = [_current, value];
else _headers[name] = value;
}
delete(name) {
name = validateHeader(name);
this._node.req.headers[name] = void 0;
}
get(name) {
name = validateHeader(name);
const rawValue = this._node.req.headers[name];
if (rawValue === void 0) return null;
return _normalizeValue(this._node.req.headers[name]);
}
getSetCookie() {
const setCookie = this._node.req.headers["set-cookie"];
if (!setCookie || setCookie.length === 0) return [];
return splitSetCookieString(setCookie);
}
has(name) {
name = validateHeader(name);
return !!this._node.req.headers[name];
}
set(name, value) {
name = validateHeader(name);
this._node.req.headers[name] = value;
}
get count() {
throw new Error("Method not implemented.");
}
getAll(_name) {
throw new Error("Method not implemented.");
}
toJSON() {
const _headers = this._node.req.headers;
const result = {};
for (const key in _headers) if (_headers[key]) result[key] = _normalizeValue(_headers[key]);
return result;
}
forEach(cb, thisArg) {
const _headers = this._node.req.headers;
for (const key in _headers) if (_headers[key]) cb.call(thisArg, _normalizeValue(_headers[key]), key, this);
}
*entries() {
const headers = this._node.req.headers;
const isHttp2 = this._node.req.httpVersion === "2.0";
for (const key in headers) if (!isHttp2 || key[0] !== ":") yield [key, _normalizeValue(headers[key])];
}
*keys() {
const keys = Object.keys(this._node.req.headers);
for (const key of keys) yield key;
}
*values() {
const values = Object.values(this._node.req.headers);
for (const value of values) yield _normalizeValue(value);
}
[Symbol.iterator]() {
return this.entries()[Symbol.iterator]();
}
get [Symbol.toStringTag]() {
return "Headers";
}
[kNodeInspect]() {
return Object.fromEntries(this.entries());
}
};
Object.setPrototypeOf(_Headers.prototype, globalThis.Headers.prototype);
return _Headers;
})();
const NodeResponseHeaders = /* @__PURE__ */ (() => {
const _Headers = class Headers$1 {
_node;
constructor(nodeCtx) {
this._node = nodeCtx;
}
append(name, value) {
this._node.res.appendHeader(name, value);
}
delete(name) {
this._node.res.removeHeader(name);
}
get(name) {
const rawValue = this._node.res.getHeader(name);
if (rawValue === void 0) return null;
return _normalizeValue(rawValue);
}
getSetCookie() {
const setCookie = _normalizeValue(this._node.res.getHeader("set-cookie"));
if (!setCookie) return [];
return splitSetCookieString(setCookie);
}
has(name) {
return this._node.res.hasHeader(name);
}
set(name, value) {
this._node.res.setHeader(name, value);
}
get count() {
throw new Error("Method not implemented.");
}
getAll(_name) {
throw new Error("Method not implemented.");
}
toJSON() {
const _headers = this._node.res.getHeaders();
const result = {};
for (const key in _headers) if (_headers[key]) result[key] = _normalizeValue(_headers[key]);
return result;
}
forEach(cb, thisArg) {
const _headers = this._node.res.getHeaders();
for (const key in _headers) if (_headers[key]) cb.call(thisArg, _normalizeValue(_headers[key]), key, this);
}
*entries() {
const _headers = this._node.res.getHeaders();
for (const key in _headers) yield [key, _normalizeValue(_headers[key])];
}
*keys() {
const keys = this._node.res.getHeaderNames();
for (const key of keys) yield key;
}
*values() {
const values = Object.values(this._node.res.getHeaders());
for (const value of values) yield _normalizeValue(value);
}
[Symbol.iterator]() {
return this.entries()[Symbol.iterator]();
}
get [Symbol.toStringTag]() {
return "Headers";
}
[kNodeInspect]() {
return Object.fromEntries(this.entries());
}
};
Object.setPrototypeOf(_Headers.prototype, globalThis.Headers.prototype);
return _Headers;
})();
function _normalizeValue(value) {
if (Array.isArray(value)) return value.join(", ");
return typeof value === "string" ? value : String(value ?? "");
}
function validateHeader(name) {
if (name[0] === ":") throw new TypeError(`${JSON.stringify(name)} is an invalid header name.`);
return name.toLowerCase();
}
//#endregion
//#region src/adapters/_node/response.ts
/**
* Fast Response for Node.js runtime
*
* It is faster because in most cases it doesn't create a full Response instance.
*/
const NodeResponse = /* @__PURE__ */ (() => {
const NativeResponse = globalThis.Response;
const STATUS_CODES = globalThis.process?.getBuiltinModule("node:http")?.STATUS_CODES || {};
class NodeResponse$1 {
#body;
#init;
#headers;
#response;
constructor(body, init) {
this.#body = body;
this.#init = init;
}
get status() {
return this.#response?.status || this.#init?.status || 200;
}
get statusText() {
return this.#response?.statusText || this.#init?.statusText || STATUS_CODES[this.status] || "";
}
get headers() {
if (this.#response) return this.#response.headers;
if (this.#headers) return this.#headers;
const initHeaders = this.#init?.headers;
return this.#headers = initHeaders instanceof Headers ? initHeaders : new Headers(initHeaders);
}
get ok() {
if (this.#response) return this.#response.ok;
const status = this.status;
return status >= 200 && status < 300;
}
get _response() {
if (this.#response) return this.#response;
this.#response = new NativeResponse(this.#body, this.#headers ? {
...this.#init,
headers: this.#headers
} : this.#init);
this.#init = void 0;
this.#headers = void 0;
this.#body = void 0;
return this.#response;
}
nodeResponse() {
const status = this.status;
const statusText = this.statusText;
let body;
let contentType;
let contentLength;
if (this.#response) body = this.#response.body;
else if (this.#body) if (this.#body instanceof ReadableStream) body = this.#body;
else if (typeof this.#body === "string") {
body = this.#body;
contentType = "text/plain; charset=UTF-8";
contentLength = Buffer.byteLength(this.#body);
} else if (this.#body instanceof ArrayBuffer) {
body = Buffer.from(this.#body);
contentLength = this.#body.byteLength;
} else if (this.#body instanceof Uint8Array) {
body = this.#body;
contentLength = this.#body.byteLength;
} else if (this.#body instanceof DataView) {
body = Buffer.from(this.#body.buffer);
contentLength = this.#body.byteLength;
} else if (this.#body instanceof Blob) {
body = this.#body.stream();
contentType = this.#body.type;
contentLength = this.#body.size;
} else if (typeof this.#body.pipe === "function") body = this.#body;
else body = this._response.body;
const rawNodeHeaders = [];
const initHeaders = this.#init?.headers;
const headerEntries = this.#response?.headers || this.#headers || (initHeaders ? Array.isArray(initHeaders) ? initHeaders : initHeaders?.entries ? initHeaders.entries() : Object.entries(initHeaders).map(([k, v]) => [k.toLowerCase(), v]) : void 0);
let hasContentTypeHeader;
let hasContentLength;
if (headerEntries) for (const [key, value] of headerEntries) {
if (key === "set-cookie") {
for (const setCookie of splitSetCookieString(value)) rawNodeHeaders.push(["set-cookie", setCookie]);
continue;
}
rawNodeHeaders.push([key, value]);
if (key === "content-type") hasContentTypeHeader = true;
else if (key === "content-length") hasContentLength = true;
}
if (contentType && !hasContentTypeHeader) rawNodeHeaders.push(["content-type", contentType]);
if (contentLength && !hasContentLength) rawNodeHeaders.push(["content-length", String(contentLength)]);
this.#init = void 0;
this.#headers = void 0;
this.#response = void 0;
this.#body = void 0;
return {
status,
statusText,
headers: rawNodeHeaders,
body
};
}
}
inheritProps(NodeResponse$1.prototype, NativeResponse.prototype, "_response");
Object.setPrototypeOf(NodeResponse$1, NativeResponse);
Object.setPrototypeOf(NodeResponse$1.prototype, NativeResponse.prototype);
return NodeResponse$1;
})();
//#endregion
export { NodeRequestHeaders, NodeResponse, NodeResponseHeaders, inheritProps, kNodeInspect };

268
node_modules/srvx/dist/_chunks/types-BtByT9ny.d.mts generated vendored Normal file
View file

@ -0,0 +1,268 @@
import * as cloudflare_workers0 from "cloudflare:workers";
import * as NodeHttp$1 from "node:http";
import * as NodeHttps from "node:https";
import * as NodeHttp2 from "node:http2";
import * as NodeNet from "node:net";
import * as Bun from "bun";
import * as CF from "@cloudflare/workers-types";
//#region src/types.d.ts
// Utils
type MaybePromise<T> = T | Promise<T>;
type IsAny<T> = Equal<T, any> extends true ? true : false;
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;
// ----------------------------------------------------------------------------
// srvx API
// ----------------------------------------------------------------------------
/**
* Faster URL constructor with lazy access to pathname and search params (For Node, Deno, and Bun).
*/
declare const FastURL: typeof globalThis.URL;
/**
* Faster Response constructor optimized for Node.js (same as Response for other runtimes).
*/
declare const FastResponse: typeof globalThis.Response;
/**
* Create a new server instance.
*/
declare function serve(options: ServerOptions): Server;
/**
* Web fetch compatible request handler
*/
type ServerHandler = (request: ServerRequest) => MaybePromise<Response>;
type ServerMiddleware = (request: ServerRequest, next: () => Response | Promise<Response>) => Response | Promise<Response>;
type ServerPlugin = (server: Server) => void;
/**
* Server options
*/
interface ServerOptions {
/**
* The fetch handler handles incoming requests.
*/
fetch: ServerHandler;
/**
* Handle lifecycle errors.
*
* @note This handler will set built-in Bun and Deno error handler.
*/
error?: ErrorHandler;
/**
* Server middleware handlers to run before the main fetch handler.
*/
middleware?: ServerMiddleware[];
/**
* Server plugins.
*/
plugins?: ServerPlugin[];
/**
* If set to `true`, server will not start listening automatically.
*/
manual?: boolean;
/**
* The port server should be listening to.
*
* Default is read from `PORT` environment variable or will be `3000`.
*
* **Tip:** You can set the port to `0` to use a random port.
*/
port?: string | number;
/**
* The hostname (IP or resolvable host) server listener should bound to.
*
* When not provided, server with listen to all network interfaces by default.
*
* **Important:** If you are running a server that is not expected to be exposed to the network, use `hostname: "localhost"`.
*/
hostname?: string;
/**
* Enabling this option allows multiple processes to bind to the same port, which is useful for load balancing.
*
* **Note:** Despite Node.js built-in behavior that has `exclusive` flag (opposite of `reusePort`) enabled by default, srvx uses non-exclusive mode for consistency.
*/
reusePort?: boolean;
/**
* The protocol to use for the server.
*
* Possible values are `http` and `https`.
*
* If `protocol` is not set, Server will use `http` as the default protocol or `https` if both `tls.cert` and `tls.key` options are provided.
*/
protocol?: "http" | "https";
/**
* If set to `true`, server will not print the listening address.
*/
silent?: boolean;
/**
* TLS server options.
*/
tls?: {
/**
* File path or inlined TLS certificate in PEM format (required).
*/
cert?: string;
/**
* File path or inlined TLS private key in PEM format (required).
*/
key?: string;
/**
* Passphrase for the private key (optional).
*/
passphrase?: string;
};
/**
* Node.js server options.
*/
node?: (NodeHttp$1.ServerOptions | NodeHttps.ServerOptions | NodeHttp2.ServerOptions) & NodeNet.ListenOptions & {
http2?: boolean;
};
/**
* Bun server options
*
* @docs https://bun.sh/docs/api/http
*/
bun?: Omit<Bun.ServeOptions | Bun.TLSServeOptions, "fetch">;
/**
* Deno server options
*
* @docs https://docs.deno.com/api/deno/~/Deno.serve
*/
deno?: Deno.ServeOptions;
/**
* Service worker options
*/
serviceWorker?: {
/**
* The path to the service worker file to be registered.
*/
url?: string;
/**
* The scope of the service worker.
*
*/
scope?: string;
};
}
interface Server<Handler = ServerHandler> {
/**
* Current runtime name
*/
readonly runtime: "node" | "deno" | "bun" | "cloudflare" | "service-worker" | "generic";
/**
* Server options
*/
readonly options: ServerOptions & {
middleware: ServerMiddleware[];
};
/**
* Server URL address.
*/
readonly url?: string;
/**
* Node.js context.
*/
readonly node?: {
server?: NodeHttp$1.Server | NodeHttp2.Http2Server;
handler: (req: NodeServerRequest, res: NodeServerResponse) => void | Promise<void>;
};
/**
* Bun context.
*/
readonly bun?: {
server?: Bun.Server;
};
/**
* Deno context.
*/
readonly deno?: {
server?: Deno.HttpServer;
};
/**
* Server fetch handler
*/
readonly fetch: Handler;
/**
* Start listening for incoming requests.
* When `manual` option is enabled, this method needs to be called explicitly to begin accepting connections.
*/
serve(): void | Promise<Server<Handler>>;
/**
* Returns a promise that resolves when the server is ready.
*/
ready(): Promise<Server<Handler>>;
/**
* Stop listening to prevent new connections from being accepted.
*
* By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops.
*
* @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections.
* @default false
*/
close(closeActiveConnections?: boolean): Promise<void>;
}
// ----------------------------------------------------------------------------
// Request with runtime addons.
// ----------------------------------------------------------------------------
interface ServerRuntimeContext {
name: "node" | "deno" | "bun" | "cloudflare" | (string & {});
/**
* Underlying Node.js server request info.
*/
node?: {
req: NodeServerRequest;
res?: NodeServerResponse;
};
/**
* Underlying Deno server request info.
*/
deno?: {
info: Deno.ServeHandlerInfo<Deno.NetAddr>;
};
/**
* Underlying Bun server request context.
*/
bun?: {
server: Bun.Server;
};
/**
* Underlying Cloudflare request context.
*/
cloudflare?: {
context: CF.ExecutionContext;
env: IsAny<typeof cloudflare_workers0> extends true ? Record<string, unknown> : typeof cloudflare_workers0.env;
};
}
interface ServerRequestContext {
[key: string]: unknown;
}
interface ServerRequest extends Request {
/**
* Runtime specific request context.
*/
runtime?: ServerRuntimeContext;
/**
* IP address of the client.
*/
ip?: string | undefined;
/**
* Arbitrary context related to the request.
*/
context?: ServerRequestContext;
/**
* Tell the runtime about an ongoing operation that shouldn't close until the promise resolves.
*/
waitUntil?: (promise: Promise<unknown>) => void | Promise<void>;
}
// ----------------------------------------------------------------------------
// Different handler types
// ----------------------------------------------------------------------------
type FetchHandler = (request: Request) => Response | Promise<Response>;
type ErrorHandler = (error: unknown) => Response | Promise<Response>;
type BunFetchHandler = (request: Request, server?: Bun.Server) => Response | Promise<Response>;
type DenoFetchHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.NetAddr>) => Response | Promise<Response>;
type NodeServerRequest = NodeHttp$1.IncomingMessage | NodeHttp2.Http2ServerRequest;
type NodeServerResponse = NodeHttp$1.ServerResponse | NodeHttp2.Http2ServerResponse;
type NodeHttpHandler = (req: NodeServerRequest, res: NodeServerResponse) => void | Promise<void>;
type NodeHTTPMiddleware = (req: NodeServerRequest, res: NodeServerResponse, next: (error?: Error) => void) => unknown | Promise<unknown>;
type CloudflareFetchHandler = CF.ExportedHandlerFetchHandler;
//#endregion
export { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTPMiddleware, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, serve };

23
node_modules/srvx/dist/adapters/bun.d.mts generated vendored Normal file
View file

@ -0,0 +1,23 @@
import { BunFetchHandler, Server, ServerOptions } from "../_chunks/types-BtByT9ny.mjs";
import { FastURL$2 as FastURL } from "../_chunks/_url-D8u5OAto.mjs";
import * as bun from "bun";
//#region src/adapters/bun.d.ts
declare const FastResponse: typeof globalThis.Response;
declare function serve(options: ServerOptions): BunServer;
// https://bun.sh/docs/api/http
declare class BunServer implements Server<BunFetchHandler> {
#private;
readonly runtime = "bun";
readonly options: Server["options"];
readonly bun: Server["bun"];
readonly serveOptions: bun.ServeOptions | bun.TLSServeOptions;
readonly fetch: BunFetchHandler;
constructor(options: ServerOptions);
serve(): Promise<this>;
get url(): string | undefined;
ready(): Promise<this>;
close(closeAll?: boolean): Promise<void>;
}
//#endregion
export { FastResponse, FastURL, serve };

81
node_modules/srvx/dist/adapters/bun.mjs generated vendored Normal file
View file

@ -0,0 +1,81 @@
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "../_chunks/_utils-DRF_4b_y.mjs";
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
import { FastURL$1 as FastURL } from "../_chunks/_url-CdE4ce6F.mjs";
//#region src/adapters/bun.ts
const FastResponse = Response;
function serve(options) {
return new BunServer(options);
}
var BunServer = class {
runtime = "bun";
options;
bun = {};
serveOptions;
fetch;
#wait;
constructor(options) {
this.options = {
...options,
middleware: [...options.middleware || []]
};
for (const plugin of options.plugins || []) plugin(this);
const fetchHandler = wrapFetch(this);
this.#wait = createWaitUntil();
this.fetch = (request, server) => {
Object.defineProperties(request, {
waitUntil: { value: this.#wait.waitUntil },
runtime: {
enumerable: true,
value: {
name: "bun",
bun: { server }
}
},
ip: {
enumerable: true,
get() {
return server?.requestIP(request)?.address;
}
}
});
return fetchHandler(request);
};
const tls = resolveTLSOptions(this.options);
this.serveOptions = {
...resolvePortAndHost(this.options),
reusePort: this.options.reusePort,
error: this.options.error,
...this.options.bun,
tls: {
cert: tls?.cert,
key: tls?.key,
passphrase: tls?.passphrase,
...this.options.bun?.tls
},
fetch: this.fetch
};
if (!options.manual) this.serve();
}
serve() {
if (!this.bun.server) this.bun.server = Bun.serve(this.serveOptions);
printListening(this.options, this.url);
return Promise.resolve(this);
}
get url() {
const server = this.bun?.server;
if (!server) return;
const address = server.address;
if (address) return fmtURL(address.address, address.port, server.protocol === "https");
return server.url.href;
}
ready() {
return Promise.resolve(this);
}
async close(closeAll) {
await Promise.all([this.#wait.wait(), Promise.resolve(this.bun?.server?.stop(closeAll))]);
}
};
//#endregion
export { FastResponse, FastURL, serve };

9
node_modules/srvx/dist/adapters/cloudflare.d.mts generated vendored Normal file
View file

@ -0,0 +1,9 @@
import { Server, ServerOptions } from "../_chunks/types-BtByT9ny.mjs";
import * as CF from "@cloudflare/workers-types";
//#region src/adapters/cloudflare.d.ts
declare const FastURL: typeof globalThis.URL;
declare const FastResponse: typeof globalThis.Response;
declare function serve(options: ServerOptions): Server<CF.ExportedHandlerFetchHandler>;
//#endregion
export { FastResponse, FastURL, serve };

62
node_modules/srvx/dist/adapters/cloudflare.mjs generated vendored Normal file
View file

@ -0,0 +1,62 @@
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
import { errorPlugin } from "../_chunks/_plugins-DOhVIkXu.mjs";
//#region src/adapters/cloudflare.ts
const FastURL = URL;
const FastResponse = Response;
function serve(options) {
return new CloudflareServer(options);
}
var CloudflareServer = class {
runtime = "cloudflare";
options;
serveOptions;
fetch;
constructor(options) {
this.options = {
...options,
middleware: [...options.middleware || []]
};
for (const plugin of options.plugins || []) plugin(this);
errorPlugin(this);
const fetchHandler = wrapFetch(this);
this.fetch = (request, env, context) => {
Object.defineProperties(request, {
waitUntil: { value: context.waitUntil.bind(context) },
runtime: {
enumerable: true,
value: {
name: "cloudflare",
cloudflare: {
env,
context
}
}
},
ip: {
enumerable: true,
get() {
return request.headers.get("cf-connecting-ip");
}
}
});
return fetchHandler(request);
};
this.serveOptions = { fetch: this.fetch };
if (!options.manual) this.serve();
}
serve() {
addEventListener("fetch", (event) => {
event.respondWith(this.fetch(event.request, {}, event));
});
}
ready() {
return Promise.resolve().then(() => this);
}
close() {
return Promise.resolve();
}
};
//#endregion
export { FastResponse, FastURL, serve };

22
node_modules/srvx/dist/adapters/deno.d.mts generated vendored Normal file
View file

@ -0,0 +1,22 @@
import { DenoFetchHandler, Server, ServerOptions } from "../_chunks/types-BtByT9ny.mjs";
import { FastURL$2 as FastURL } from "../_chunks/_url-D8u5OAto.mjs";
//#region src/adapters/deno.d.ts
declare const FastResponse: typeof globalThis.Response;
declare function serve(options: ServerOptions): DenoServer;
// https://docs.deno.com/api/deno/~/Deno.serve
declare class DenoServer implements Server<DenoFetchHandler> {
#private;
readonly runtime = "deno";
readonly options: Server["options"];
readonly deno: Server["deno"];
readonly serveOptions: Deno.ServeTcpOptions | (Deno.ServeTcpOptions & Deno.TlsCertifiedKeyPem);
readonly fetch: DenoFetchHandler;
constructor(options: ServerOptions);
serve(): Promise<this>;
get url(): string | undefined;
ready(): Promise<Server>;
close(): Promise<void>;
}
//#endregion
export { FastResponse, FastURL, serve };

90
node_modules/srvx/dist/adapters/deno.mjs generated vendored Normal file
View file

@ -0,0 +1,90 @@
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "../_chunks/_utils-DRF_4b_y.mjs";
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
import { FastURL$1 as FastURL } from "../_chunks/_url-CdE4ce6F.mjs";
//#region src/adapters/deno.ts
const FastResponse = Response;
function serve(options) {
return new DenoServer(options);
}
var DenoServer = class {
runtime = "deno";
options;
deno = {};
serveOptions;
fetch;
#listeningPromise;
#listeningInfo;
#wait;
constructor(options) {
this.options = {
...options,
middleware: [...options.middleware || []]
};
for (const plugin of options.plugins || []) plugin(this);
const fetchHandler = wrapFetch(this);
this.#wait = createWaitUntil();
this.fetch = (request, info) => {
Object.defineProperties(request, {
waitUntil: { value: this.#wait.waitUntil },
runtime: {
enumerable: true,
value: {
name: "deno",
deno: {
info,
server: this.deno?.server
}
}
},
ip: {
enumerable: true,
get() {
return (info?.remoteAddr)?.hostname;
}
}
});
return fetchHandler(request);
};
const tls = resolveTLSOptions(this.options);
this.serveOptions = {
...resolvePortAndHost(this.options),
reusePort: this.options.reusePort,
onError: this.options.error,
...tls ? {
key: tls.key,
cert: tls.cert,
passphrase: tls.passphrase
} : {},
...this.options.deno
};
if (!options.manual) this.serve();
}
serve() {
if (this.deno?.server) return Promise.resolve(this.#listeningPromise).then(() => this);
const onListenPromise = Promise.withResolvers();
this.#listeningPromise = onListenPromise.promise;
this.deno.server = Deno.serve({
...this.serveOptions,
onListen: (info) => {
this.#listeningInfo = info;
if (this.options.deno?.onListen) this.options.deno.onListen(info);
printListening(this.options, this.url);
onListenPromise.resolve();
}
}, this.fetch);
return Promise.resolve(this.#listeningPromise).then(() => this);
}
get url() {
return this.#listeningInfo ? fmtURL(this.#listeningInfo.hostname, this.#listeningInfo.port, !!this.serveOptions.cert) : void 0;
}
ready() {
return Promise.resolve(this.#listeningPromise).then(() => this);
}
async close() {
await Promise.all([this.#wait.wait(), Promise.resolve(this.deno?.server?.shutdown())]);
}
};
//#endregion
export { FastResponse, FastURL, serve };

8
node_modules/srvx/dist/adapters/generic.d.mts generated vendored Normal file
View file

@ -0,0 +1,8 @@
import { Server, ServerOptions } from "../_chunks/types-BtByT9ny.mjs";
//#region src/adapters/generic.d.ts
declare const FastURL: typeof globalThis.URL;
declare const FastResponse: typeof globalThis.Response;
declare function serve(options: ServerOptions): Server;
//#endregion
export { FastResponse, FastURL, serve };

40
node_modules/srvx/dist/adapters/generic.mjs generated vendored Normal file
View file

@ -0,0 +1,40 @@
import { createWaitUntil } from "../_chunks/_utils-DRF_4b_y.mjs";
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
import { errorPlugin } from "../_chunks/_plugins-DOhVIkXu.mjs";
//#region src/adapters/generic.ts
const FastURL = URL;
const FastResponse = Response;
function serve(options) {
return new GenericServer(options);
}
var GenericServer = class {
runtime = "generic";
options;
fetch;
#wait;
constructor(options) {
this.options = {
...options,
middleware: [...options.middleware || []]
};
for (const plugin of options.plugins || []) plugin(this);
errorPlugin(this);
this.#wait = createWaitUntil();
const fetchHandler = wrapFetch(this);
this.fetch = (request) => {
Object.defineProperties(request, { waitUntil: { value: this.#wait.waitUntil } });
return Promise.resolve(fetchHandler(request));
};
}
serve() {}
ready() {
return Promise.resolve(this);
}
async close() {
await this.#wait.wait();
}
};
//#endregion
export { FastResponse, FastURL, serve };

58
node_modules/srvx/dist/adapters/node.d.mts generated vendored Normal file
View file

@ -0,0 +1,58 @@
import { FetchHandler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerOptions, ServerRequest } from "../_chunks/types-BtByT9ny.mjs";
import { FastURL$2 as FastURL } from "../_chunks/_url-D8u5OAto.mjs";
import NodeHttp from "node:http";
import { Readable } from "node:stream";
//#region src/adapters/_node/request.d.ts
type NodeRequestContext = {
req: NodeServerRequest;
res?: NodeServerResponse;
};
declare const NodeRequest: {
new (nodeCtx: NodeRequestContext): ServerRequest;
};
//#endregion
//#region src/adapters/_node/headers.d.ts
type NodeRequestHeaders = InstanceType<typeof NodeRequestHeaders>;
declare const NodeRequestHeaders: {
new (nodeCtx: {
req: NodeServerRequest;
res?: NodeServerResponse;
}): globalThis.Headers;
};
declare const NodeResponseHeaders: {
new (nodeCtx: {
req?: NodeServerRequest;
res: NodeServerResponse;
}): globalThis.Headers;
};
//#endregion
//#region src/adapters/_node/response.d.ts
// prettier-ignore
type PreparedNodeResponseBody = string | Buffer | Uint8Array | DataView | ReadableStream | Readable | undefined | null;
interface PreparedNodeResponse {
status: number;
statusText: string;
headers: NodeHttp.OutgoingHttpHeader[];
body: PreparedNodeResponseBody;
}
/**
* Fast Response for Node.js runtime
*
* It is faster because in most cases it doesn't create a full Response instance.
*/
declare const NodeResponse: {
new (body?: BodyInit | null, init?: ResponseInit): globalThis.Response & {
readonly nodeResponse: () => PreparedNodeResponse;
};
};
type NodeResponse = InstanceType<typeof NodeResponse>;
//#endregion
//#region src/adapters/_node/send.d.ts
declare function sendNodeResponse(nodeRes: NodeServerResponse, webRes: Response | NodeResponse): Promise<void>;
//#endregion
//#region src/adapters/node.d.ts
declare function serve(options: ServerOptions): Server;
declare function toNodeHandler(fetchHandler: FetchHandler): NodeHttpHandler;
//#endregion
export { NodeResponse as FastResponse, FastURL, NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, sendNodeResponse, serve, toNodeHandler };

398
node_modules/srvx/dist/adapters/node.mjs generated vendored Normal file
View file

@ -0,0 +1,398 @@
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "../_chunks/_utils-DRF_4b_y.mjs";
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
import { FastURL$1 as FastURL } from "../_chunks/_url-CdE4ce6F.mjs";
import { NodeRequestHeaders, NodeResponse, NodeResponseHeaders, inheritProps, kNodeInspect } from "../_chunks/response-6LJL3Qlz.mjs";
import { errorPlugin } from "../_chunks/_plugins-DOhVIkXu.mjs";
import { splitSetCookieString } from "cookie-es";
//#region src/adapters/_node/send.ts
async function sendNodeResponse(nodeRes, webRes) {
if (!webRes) {
nodeRes.statusCode = 500;
return endNodeResponse(nodeRes);
}
if (webRes.nodeResponse) {
const res = webRes.nodeResponse();
writeHead(nodeRes, res.status, res.statusText, res.headers.flat());
if (res.body) {
if (res.body instanceof ReadableStream) return streamBody(res.body, nodeRes);
else if (typeof res.body?.pipe === "function") {
res.body.pipe(nodeRes);
return new Promise((resolve) => nodeRes.on("close", resolve));
}
nodeRes.write(res.body);
}
return endNodeResponse(nodeRes);
}
const headerEntries = [];
for (const [key, value] of webRes.headers) if (key === "set-cookie") for (const setCookie of splitSetCookieString(value)) headerEntries.push(["set-cookie", setCookie]);
else headerEntries.push([key, value]);
writeHead(nodeRes, webRes.status, webRes.statusText, headerEntries.flat());
return webRes.body ? streamBody(webRes.body, nodeRes) : endNodeResponse(nodeRes);
}
function writeHead(nodeRes, status, statusText, headers) {
if (!nodeRes.headersSent) if (nodeRes.req?.httpVersion === "2.0") nodeRes.writeHead(status, headers.flat());
else nodeRes.writeHead(status, statusText, headers.flat());
}
function endNodeResponse(nodeRes) {
return new Promise((resolve) => nodeRes.end(resolve));
}
function streamBody(stream, nodeRes) {
if (nodeRes.destroyed) {
stream.cancel();
return;
}
const reader = stream.getReader();
function streamCancel(error) {
reader.cancel(error).catch(() => {});
if (error) nodeRes.destroy(error);
}
function streamHandle({ done, value }) {
try {
if (done) nodeRes.end();
else if (nodeRes.write(value)) reader.read().then(streamHandle, streamCancel);
else nodeRes.once("drain", () => reader.read().then(streamHandle, streamCancel));
} catch (error) {
streamCancel(error instanceof Error ? error : void 0);
}
}
nodeRes.on("close", streamCancel);
nodeRes.on("error", streamCancel);
reader.read().then(streamHandle, streamCancel);
return reader.closed.finally(() => {
nodeRes.off("close", streamCancel);
nodeRes.off("error", streamCancel);
});
}
//#endregion
//#region src/adapters/_node/url.ts
const NodeRequestURL = /* @__PURE__ */ (() => {
const _URL = class URL {
_node;
_hash = "";
_username = "";
_password = "";
_protocol;
_hostname;
_port;
_pathname;
_search;
_searchParams;
constructor(nodeCtx) {
this._node = nodeCtx;
}
get hash() {
return this._hash;
}
set hash(value) {
this._hash = value;
}
get username() {
return this._username;
}
set username(value) {
this._username = value;
}
get password() {
return this._password;
}
set password(value) {
this._password = value;
}
get host() {
return this._node.req.headers.host || this._node.req.headers[":authority"] || "";
}
set host(value) {
this._hostname = void 0;
this._port = void 0;
this._node.req.headers.host = value;
}
get hostname() {
if (this._hostname === void 0) {
const [hostname, port] = parseHost(this._node.req.headers.host);
if (this._port === void 0 && port) this._port = String(Number.parseInt(port) || "");
this._hostname = hostname || "localhost";
}
return this._hostname;
}
set hostname(value) {
this._hostname = value;
}
get port() {
if (this._port === void 0) {
const [hostname, port] = parseHost(this._node.req.headers.host);
if (this._hostname === void 0 && hostname) this._hostname = hostname;
this._port = port || String(this._node.req.socket?.localPort || "");
}
return this._port;
}
set port(value) {
this._port = String(Number.parseInt(value) || "");
}
get pathname() {
if (this._pathname === void 0) {
const [pathname, search] = parsePath(this._node.req.url || "/");
this._pathname = pathname;
if (this._search === void 0) this._search = search;
}
return this._pathname;
}
set pathname(value) {
if (value[0] !== "/") value = "/" + value;
if (value === this._pathname) return;
this._pathname = value;
this._node.req.url = value + this.search;
}
get search() {
if (this._search === void 0) {
const [pathname, search] = parsePath(this._node.req.url || "/");
this._search = search;
if (this._pathname === void 0) this._pathname = pathname;
}
return this._search;
}
set search(value) {
if (value === "?") value = "";
else if (value && value[0] !== "?") value = "?" + value;
if (value === this._search) return;
this._search = value;
this._searchParams = void 0;
this._node.req.url = this.pathname + value;
}
get searchParams() {
if (!this._searchParams) this._searchParams = new URLSearchParams(this.search);
return this._searchParams;
}
set searchParams(value) {
this._searchParams = value;
this._search = value.toString();
}
get protocol() {
if (!this._protocol) this._protocol = this._node.req.socket?.encrypted || this._node.req.headers["x-forwarded-proto"] === "https" ? "https:" : "http:";
return this._protocol;
}
set protocol(value) {
this._protocol = value;
}
get origin() {
return `${this.protocol}//${this.host}`;
}
set origin(_value) {}
get href() {
return `${this.protocol}//${this.host}${this.pathname}${this.search}`;
}
set href(value) {
const _url = new globalThis.URL(value);
this._protocol = _url.protocol;
this.username = _url.username;
this.password = _url.password;
this._hostname = _url.hostname;
this._port = _url.port;
this.pathname = _url.pathname;
this.search = _url.search;
this.hash = _url.hash;
}
toString() {
return this.href;
}
toJSON() {
return this.href;
}
get [Symbol.toStringTag]() {
return "URL";
}
[kNodeInspect]() {
return this.href;
}
};
Object.setPrototypeOf(_URL.prototype, globalThis.URL.prototype);
return _URL;
})();
function parsePath(input) {
const url = (input || "/").replace(/\\/g, "/");
const qIndex = url.indexOf("?");
if (qIndex === -1) return [url, ""];
return [url.slice(0, qIndex), url.slice(qIndex)];
}
function parseHost(host) {
const s = (host || "").split(":");
return [s[0], String(Number.parseInt(s[1]) || "")];
}
//#endregion
//#region src/adapters/_node/request.ts
const NodeRequest = /* @__PURE__ */ (() => {
const { Readable } = process.getBuiltinModule("node:stream");
const NativeRequest = globalThis._Request ??= globalThis.Request;
const PatchedRequest = class Request extends NativeRequest {
static _srvx = true;
constructor(input, options) {
if (typeof input === "object" && "_request" in input) input = input._request;
if ((options?.body)?.getReader !== void 0) options.duplex ??= "half";
super(input, options);
}
};
if (!globalThis.Request._srvx) globalThis.Request = PatchedRequest;
class NodeRequest$1 {
_node;
_url;
runtime;
#request;
#headers;
#abortSignal;
constructor(ctx) {
this._node = ctx;
this._url = new NodeRequestURL({ req: ctx.req });
this.runtime = {
name: "node",
node: ctx
};
}
get ip() {
return this._node.req.socket?.remoteAddress;
}
get method() {
return this._node.req.method || "GET";
}
get url() {
return this._url.href;
}
get headers() {
return this.#headers ||= new NodeRequestHeaders(this._node);
}
get signal() {
if (!this.#abortSignal) {
this.#abortSignal = new AbortController();
this._node.req.once("close", () => {
this.#abortSignal?.abort();
});
}
return this.#abortSignal.signal;
}
get _request() {
if (!this.#request) {
const method = this.method;
const hasBody = !(method === "GET" || method === "HEAD");
this.#request = new PatchedRequest(this.url, {
method,
headers: this.headers,
signal: this.signal,
body: hasBody ? Readable.toWeb(this._node.req) : void 0
});
}
return this.#request;
}
}
inheritProps(NodeRequest$1.prototype, NativeRequest.prototype, "_request");
Object.setPrototypeOf(NodeRequest$1.prototype, PatchedRequest.prototype);
return NodeRequest$1;
})();
//#endregion
//#region src/adapters/node.ts
function serve(options) {
return new NodeServer(options);
}
function toNodeHandler(fetchHandler) {
return (nodeReq, nodeRes) => {
const request = new NodeRequest({
req: nodeReq,
res: nodeRes
});
const res = fetchHandler(request);
return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
};
}
var NodeServer = class {
runtime = "node";
options;
node;
serveOptions;
fetch;
#isSecure;
#listeningPromise;
#wait;
constructor(options) {
this.options = {
...options,
middleware: [...options.middleware || []]
};
for (const plugin of options.plugins || []) plugin(this);
errorPlugin(this);
const fetchHandler = this.fetch = wrapFetch(this);
this.#wait = createWaitUntil();
const handler = (nodeReq, nodeRes) => {
const request = new NodeRequest({
req: nodeReq,
res: nodeRes
});
request.waitUntil = this.#wait.waitUntil;
const res = fetchHandler(request);
return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
};
const tls = resolveTLSOptions(this.options);
const { port, hostname: host } = resolvePortAndHost(this.options);
this.serveOptions = {
port,
host,
exclusive: !this.options.reusePort,
...tls ? {
cert: tls.cert,
key: tls.key,
passphrase: tls.passphrase
} : {},
...this.options.node
};
let server;
this.#isSecure = !!this.serveOptions.cert && this.options.protocol !== "http";
const isHttp2 = this.options.node?.http2 ?? this.#isSecure;
if (isHttp2) if (this.#isSecure) {
const { createSecureServer } = process.getBuiltinModule("node:http2");
server = createSecureServer({
allowHTTP1: true,
...this.serveOptions
}, handler);
} else throw new Error("node.http2 option requires tls certificate!");
else if (this.#isSecure) {
const { createServer } = process.getBuiltinModule("node:https");
server = createServer(this.serveOptions, handler);
} else {
const { createServer } = process.getBuiltinModule("node:http");
server = createServer(this.serveOptions, handler);
}
this.node = {
server,
handler
};
if (!options.manual) this.serve();
}
serve() {
if (this.#listeningPromise) return Promise.resolve(this.#listeningPromise).then(() => this);
this.#listeningPromise = new Promise((resolve) => {
this.node.server.listen(this.serveOptions, () => {
printListening(this.options, this.url);
resolve();
});
});
}
get url() {
const addr = this.node?.server?.address();
if (!addr) return;
return typeof addr === "string" ? addr : fmtURL(addr.address, addr.port, this.#isSecure);
}
ready() {
return Promise.resolve(this.#listeningPromise).then(() => this);
}
async close(closeAll) {
await Promise.all([this.#wait.wait(), new Promise((resolve, reject) => {
const server = this.node?.server;
if (!server) return resolve();
if (closeAll && "closeAllConnections" in server) server.closeAllConnections();
server.close((error) => error ? reject(error) : resolve());
})]);
}
};
//#endregion
export { NodeResponse as FastResponse, FastURL, NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, sendNodeResponse, serve, toNodeHandler };

9
node_modules/srvx/dist/adapters/service-worker.d.mts generated vendored Normal file
View file

@ -0,0 +1,9 @@
import { Server, ServerOptions, ServerRequest } from "../_chunks/types-BtByT9ny.mjs";
//#region src/adapters/service-worker.d.ts
declare const FastURL: typeof globalThis.URL;
declare const FastResponse: typeof globalThis.Response;
type ServiceWorkerHandler = (request: ServerRequest, event: FetchEvent) => Response | Promise<Response>;
declare function serve(options: ServerOptions): Server<ServiceWorkerHandler>;
//#endregion
export { FastResponse, FastURL, ServiceWorkerHandler, serve };

81
node_modules/srvx/dist/adapters/service-worker.mjs generated vendored Normal file
View file

@ -0,0 +1,81 @@
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
import { errorPlugin } from "../_chunks/_plugins-DOhVIkXu.mjs";
//#region src/adapters/service-worker.ts
const FastURL = URL;
const FastResponse = Response;
const isBrowserWindow = typeof window !== "undefined" && typeof navigator !== "undefined";
const isServiceWorker = /* @__PURE__ */ (() => typeof self !== "undefined" && "skipWaiting" in self)();
function serve(options) {
return new ServiceWorkerServer(options);
}
var ServiceWorkerServer = class {
runtime = "service-worker";
options;
fetch;
#fetchListener;
#listeningPromise;
constructor(options) {
this.options = {
...options,
middleware: [...options.middleware || []]
};
for (const plugin of options.plugins || []) plugin(this);
errorPlugin(this);
const fetchHandler = wrapFetch(this);
this.fetch = (request, event) => {
Object.defineProperties(request, { runtime: {
enumerable: true,
value: {
name: "service-worker",
serviceWorker: { event }
}
} });
return Promise.resolve(fetchHandler(request));
};
if (!options.manual) this.serve();
}
serve() {
if (isBrowserWindow) {
if (!navigator.serviceWorker) throw new Error("Service worker is not supported in the current window.");
const swURL = this.options.serviceWorker?.url;
if (!swURL) throw new Error("Service worker URL is not provided. Please set the `serviceWorker.url` serve option or manually register.");
this.#listeningPromise = navigator.serviceWorker.register(swURL, {
type: "module",
scope: this.options.serviceWorker?.scope
}).then((registration) => {
if (registration.active) location.replace(location.href);
else registration.addEventListener("updatefound", () => {
location.replace(location.href);
});
});
} else if (isServiceWorker) {
this.#fetchListener = async (event) => {
if (/\/[^/]*\.[a-zA-Z0-9]+$/.test(new URL(event.request.url).pathname)) return;
Object.defineProperty(event.request, "waitUntil", { value: event.waitUntil.bind(event) });
const response = await this.fetch(event.request, event);
if (response.status !== 404) event.respondWith(response);
};
addEventListener("fetch", this.#fetchListener);
self.addEventListener("install", () => {
self.skipWaiting();
});
self.addEventListener("activate", () => {
self.clients?.claim?.();
});
}
}
ready() {
return Promise.resolve(this.#listeningPromise).then(() => this);
}
async close() {
if (this.#fetchListener) removeEventListener("fetch", this.#fetchListener);
if (isBrowserWindow) {
const registrations = await navigator.serviceWorker.getRegistrations();
for (const registration of registrations) if (registration.active) await registration.unregister();
} else if (isServiceWorker) await self.registration.unregister();
}
};
//#endregion
export { FastResponse, FastURL, serve };

17
node_modules/srvx/dist/cli.d.mts generated vendored Normal file
View file

@ -0,0 +1,17 @@
import { Server } from "srvx";
//#region src/cli.d.ts
declare function main(mainOpts: MainOpts): Promise<void>;
declare global {
var __srvx_version__: string | undefined;
var __srvx__: Server;
var __srvx_listen_cb__: () => void;
}
type MainOpts = {
command: string;
docs: string;
issues: string;
};
declare function usage(mainOpts: MainOpts): string;
//#endregion
export { main, usage };

352
node_modules/srvx/dist/cli.mjs generated vendored Normal file
View file

@ -0,0 +1,352 @@
import { Colors } from "./_chunks/_utils.cli-B2YzwlOv.mjs";
import { parseArgs } from "node:util";
import { fileURLToPath, pathToFileURL } from "node:url";
import { dirname, extname, relative, resolve } from "node:path";
import { fork } from "node:child_process";
import { existsSync } from "node:fs";
//#region src/cli.ts
const defaultEntries = [
"server",
"index",
"src/server",
"src/index",
"server/index"
];
const defaultExts = [
".mts",
".ts",
".cts",
".js",
".mjs",
".cjs",
".jsx",
".tsx"
];
const args = process.argv.slice(2);
const options = parseArgs$1(args);
if (process.send) {
setupProcessErrorHandlers();
await serve();
}
async function main(mainOpts) {
setupProcessErrorHandlers();
if (options._version) {
console.log(await version());
process.exit(0);
}
if (options._help) {
console.log(usage(mainOpts));
process.exit(options._help ? 0 : 1);
}
const isBun = !!process.versions.bun;
const isDeno = !!process.versions.deno;
const isNode = !isBun && !isDeno;
const runtimeArgs = [];
if (!options._prod) runtimeArgs.push("--watch");
if (isNode || isDeno) runtimeArgs.push(...[".env", options._prod ? ".env.production" : ".env.local"].filter((f) => existsSync(f)).map((f) => `--env-file=${f}`));
if (isNode) {
const [major, minor] = process.versions.node.split(".");
if (major === "22" && +minor >= 6) runtimeArgs.push("--experimental-strip-types");
if (options._import) runtimeArgs.push(`--import=${options._import}`);
}
const child = fork(fileURLToPath(import.meta.url), args, { execArgv: [...process.execArgv, ...runtimeArgs].filter(Boolean) });
child.on("error", (error) => {
console.error("Error in child process:", error);
process.exit(1);
});
child.on("exit", (code) => {
if (code !== 0) {
console.error(`Child process exited with code ${code}`);
process.exit(code);
}
});
}
async function serve() {
try {
if (!process.env.NODE_ENV) process.env.NODE_ENV = options._prod ? "production" : "development";
const entry = await loadEntry(options);
const forceUseNode = entry._legacyNode;
const { serve: srvxServe } = forceUseNode ? await import("srvx/node") : await import("srvx");
const { serveStatic } = await import("srvx/static");
const { log } = await import("srvx/log");
const staticDir = resolve(options._dir, options._static);
options._static = existsSync(staticDir) ? staticDir : "";
const server = srvxServe({
error: (error) => {
console.error(error);
return renderError(error);
},
middleware: [
log(),
options._static ? serveStatic({ dir: options._static }) : void 0,
...entry.middleware || []
].filter(Boolean),
...entry
});
globalThis.__srvx__ = server;
await server.ready();
await globalThis.__srvx_listen_cb__?.();
printInfo(entry);
const cleanup = () => {
server.close(true).catch(() => {});
process.exit(0);
};
process.on("SIGINT", () => {
console.log(Colors.gray("\rStopping server..."));
cleanup();
});
process.on("SIGTERM", cleanup);
} catch (error) {
console.error(error);
process.exit(1);
}
}
async function loadEntry(opts) {
try {
if (!opts._entry) for (const entry of defaultEntries) {
for (const ext of defaultExts) {
const entryPath = resolve(opts._dir, `${entry}${ext}`);
if (existsSync(entryPath)) {
opts._entry = entryPath;
break;
}
}
if (opts._entry) break;
}
if (!opts._entry) {
const _error$1 = `No server entry file found.\nPlease specify an entry file or ensure one of the default entries exists (${defaultEntries.join(", ")}).`;
return {
_error: _error$1,
fetch: () => renderError(_error$1, 404, "No Server Entry"),
...opts
};
}
const entryURL = opts._entry.startsWith("file://") ? opts._entry : pathToFileURL(resolve(opts._entry)).href;
const { res: mod, listenHandler } = await interceptListen(() => import(entryURL));
let fetchHandler = mod.fetch || mod.default?.fetch || mod.default?.default?.fetch;
let _legacyNode = false;
if (!fetchHandler) {
const nodeHandler = listenHandler || (typeof mod.default === "function" ? mod.default : void 0);
if (nodeHandler) {
_legacyNode = true;
const { callNodeHandler } = await import("./_chunks/call-LB9MY5Dv.mjs");
fetchHandler = (webReq) => callNodeHandler(nodeHandler, webReq);
}
}
let _error;
if (!fetchHandler) {
_error = `The entry file "${relative(".", opts._entry)}" does not export a valid fetch handler.`;
fetchHandler = () => renderError(_error, 500, "Invalid Entry");
}
return {
...mod,
...mod.default,
...opts,
_error,
_legacyNode,
fetch: fetchHandler
};
} catch (error) {
if (error?.code === "ERR_UNKNOWN_FILE_EXTENSION") {
const message = String(error);
if (/"\.(m|c)?ts"/g.test(message)) console.error(Colors.red(`\nMake sure you're using Node.js v22.18+ or v24+ for TypeScript support (current version: ${process.versions.node})\n\n`));
else if (/"\.(m|c)?tsx"/g.test(message)) console.error(Colors.red(`\nYou need a compatible loader for JSX support (Deno, Bun or srvx --register jiti/register)\n\n`));
}
if (error instanceof Error) Error.captureStackTrace?.(error, serve);
throw error;
}
}
function renderError(error, status = 500, title = "Server Error") {
let html = `<!DOCTYPE html><html><head><title>${title}</title></head><body>`;
if (options._prod) html += `<h1>${title}</h1><p>Something went wrong while processing your request.</p>`;
else html += `
<style>
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f8f9fa; color: #333; }
h1 { color: #dc3545; }
pre { background: #fff; padding: 10px; border-radius: 5px; overflow: auto; }
code { font-family: monospace; }
#error { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; }
</style>
<div id="error"><h1>${title}</h1><pre>${error instanceof Error ? error.stack || error.message : String(error)}</pre></div>
`;
return new Response(html, {
status,
headers: { "Content-Type": "text/html; charset=utf-8" }
});
}
function printInfo(entry) {
let entryInfo;
if (options._entry) entryInfo = Colors.cyan("./" + relative(".", options._entry));
else entryInfo = Colors.gray(`(create ${Colors.bold(`server.ts`)} to enable)`);
console.log(Colors.gray(`${Colors.bold(Colors.gray("λ"))} Server handler: ${entryInfo}`));
if (options._entry && entry._error) console.error(Colors.red(` ${entry._error}`));
let staticInfo;
if (options._static) staticInfo = Colors.cyan("./" + relative(".", options._static) + "/");
else staticInfo = Colors.gray(`(add ${Colors.bold("public/")} dir to enable)`);
console.log(Colors.gray(`${Colors.bold(Colors.gray("∘"))} Static files: ${staticInfo}`));
}
async function interceptListen(cb) {
const http = process.getBuiltinModule("node:http");
if (!http || !http.Server) {
const res$1 = await cb();
return { res: res$1 };
}
const originalListen = http.Server.prototype.listen;
let res;
let listenHandler;
try {
http.Server.prototype.listen = function(arg1, arg2) {
listenHandler = this._events.request;
if (Array.isArray(listenHandler)) listenHandler = listenHandler[0];
http.Server.prototype.listen = originalListen;
globalThis.__srvx_listen_cb__ = [arg1, arg2].find((arg) => typeof arg === "function");
return new Proxy({}, { get(_, prop) {
const server = globalThis.__srvx__;
return server?.node?.server?.[prop];
} });
};
res = await cb();
} finally {
http.Server.prototype.listen = originalListen;
}
return {
res,
listenHandler
};
}
async function version() {
const version$1 = "0.8.9";
return `srvx ${version$1}\n${runtime()}`;
}
function runtime() {
if (process.versions.bun) return `bun ${process.versions.bun}`;
else if (process.versions.deno) return `deno ${process.versions.deno}`;
else return `node ${process.versions.node}`;
}
function parseArgs$1(args$1) {
const { values, positionals } = parseArgs({
args: args$1,
allowPositionals: true,
options: {
help: {
type: "boolean",
short: "h"
},
version: {
type: "boolean",
short: "v"
},
prod: { type: "boolean" },
port: {
type: "string",
short: "p"
},
host: {
type: "string",
short: "H"
},
static: {
type: "string",
short: "s"
},
import: { type: "string" },
tls: { type: "boolean" },
cert: { type: "string" },
key: { type: "string" }
}
});
const input = positionals[0] || ".";
let dir;
let entry = "";
if (extname(input) === "") dir = resolve(input);
else {
entry = resolve(input);
dir = dirname(entry);
}
if (!existsSync(dir)) {
console.error(Colors.red(`Directory "${dir}" does not exist.\n`));
process.exit(1);
}
return {
_dir: dir,
_entry: entry,
_prod: values.prod ?? process.env.NODE_ENV === "production",
_help: values.help,
_static: values.static || "public",
_version: values.version,
_import: values.import,
port: values.port ? Number.parseInt(values.port, 10) : void 0,
hostname: values.host,
tls: values.tls ? {
cert: values.cert,
key: values.key
} : void 0
};
}
function example() {
const useTs = !options._entry || options._entry.endsWith(".ts");
return `${Colors.bold(Colors.gray("// server.ts"))}
${Colors.magenta("export default")} {
${Colors.cyan("fetch")}(req${useTs ? ": Request" : ""}) {
${Colors.magenta("return")} new Response(${Colors.green("\"Hello, World!\"")});
}
}`;
}
function usage(mainOpts) {
const command = mainOpts.command;
return `
${Colors.cyan(command)} - Start an HTTP server with the specified entry path.
${Colors.bold("USAGE")}
${existsSync(options._entry) ? "" : `\n${example()}\n`}
${Colors.gray("# srvx [options] [entry]")}
${Colors.gray("$")} ${Colors.cyan(command)} ${Colors.gray("./server.ts")} ${Colors.gray("# Start development server")}
${Colors.gray("$")} ${Colors.cyan(command)} --prod ${Colors.gray("# Start production server")}
${Colors.gray("$")} ${Colors.cyan(command)} --port=8080 ${Colors.gray("# Listen on port 8080")}
${Colors.gray("$")} ${Colors.cyan(command)} --host=localhost ${Colors.gray("# Bind to localhost only")}
${Colors.gray("$")} ${Colors.cyan(command)} --import=jiti/register ${Colors.gray(`# Enable ${Colors.url("jiti", "https://github.com/unjs/jiti")} loader`)}
${Colors.gray("$")} ${Colors.cyan(command)} --tls --cert=cert.pem --key=key.pem ${Colors.gray("# Enable TLS (HTTPS/HTTP2)")}
${Colors.bold("ARGUMENTS")}
${Colors.yellow("<entry>")} Server entry path to serve.
Default: ${defaultEntries.map((e) => Colors.cyan(e)).join(", ")} ${Colors.gray(`(${defaultExts.join(",")})`)}
${Colors.bold("OPTIONS")}
${Colors.green("-p, --port")} ${Colors.yellow("<port>")} Port to listen on (default: ${Colors.yellow("3000")})
${Colors.green("--host")} ${Colors.yellow("<host>")} Host to bind to (default: all interfaces)
${Colors.green("-s, --static")} ${Colors.yellow("<dir>")} Serve static files from the specified directory (default: ${Colors.yellow("public")})
${Colors.green("--prod")} Run in production mode (no watch, no debug)
${Colors.green("--import")} ${Colors.yellow("<loader>")} ES module to preload
${Colors.green("--tls")} Enable TLS (HTTPS/HTTP2)
${Colors.green("--cert")} ${Colors.yellow("<file>")} TLS certificate file
${Colors.green("--key")} ${Colors.yellow("<file>")} TLS private key file
${Colors.green("-h, --help")} Show this help message
${Colors.green("-v, --version")} Show server and runtime versions
${Colors.bold("ENVIRONMENT")}
${Colors.green("PORT")} Override port
${Colors.green("HOST")} Override host
${Colors.green("NODE_ENV")} Set to ${Colors.yellow("production")} for production mode.
${Colors.url("Documentation", mainOpts.docs || "https://srvx.h3.dev")}
${Colors.url("Report issues", mainOpts.issues || "https://github.com/h3js/srvx/issues")}
`.trim();
}
function setupProcessErrorHandlers() {
process.on("uncaughtException", (error) => {
console.error("Uncaught exception:", error);
process.exit(1);
});
process.on("unhandledRejection", (reason) => {
console.error("Unhandled rejection:", reason);
process.exit(1);
});
}
//#endregion
export { main, usage };

8
node_modules/srvx/dist/log.d.mts generated vendored Normal file
View file

@ -0,0 +1,8 @@
import { ServerMiddleware } from "./_chunks/types-BtByT9ny.mjs";
//#region src/log.d.ts
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface LogOptions {}
declare const log: (_options?: LogOptions) => ServerMiddleware;
//#endregion
export { LogOptions, log };

21
node_modules/srvx/dist/log.mjs generated vendored Normal file
View file

@ -0,0 +1,21 @@
import { Colors } from "./_chunks/_utils.cli-B2YzwlOv.mjs";
//#region src/log.ts
const statusColors = {
1: "blue",
2: "green",
3: "yellow"
};
const log = (_options = {}) => {
return async (req, next) => {
const start = performance.now();
const res = await next();
const duration = performance.now() - start;
const statusColor = statusColors[Math.floor(res.status / 100)] || "red";
console.log(`${Colors.gray(`[${new Date().toLocaleTimeString()}]`)} ${Colors.bold(req.method)} ${Colors.blue(req.url)} [${Colors[statusColor](res.status + "")}] ${Colors.gray(`(${duration.toFixed(2)}ms)`)}`);
return res;
};
};
//#endregion
export { log };

9
node_modules/srvx/dist/static.d.mts generated vendored Normal file
View file

@ -0,0 +1,9 @@
import { ServerMiddleware } from "./_chunks/types-BtByT9ny.mjs";
//#region src/static.d.ts
interface ServeStaticOptions {
dir: string;
}
declare const serveStatic: (options: ServeStaticOptions) => ServerMiddleware;
//#endregion
export { ServeStaticOptions, serveStatic };

70
node_modules/srvx/dist/static.mjs generated vendored Normal file
View file

@ -0,0 +1,70 @@
import { extname, join, resolve } from "node:path";
import { createReadStream } from "node:fs";
import { stat } from "node:fs/promises";
import { FastResponse } from "srvx";
import { createBrotliCompress, createGzip } from "node:zlib";
//#region src/static.ts
const COMMON_MIME_TYPES = {
".html": "text/html",
".htm": "text/html",
".css": "text/css",
".js": "text/javascript",
".mjs": "text/javascript",
".json": "application/json",
".txt": "text/plain",
".xml": "application/xml",
".gif": "image/gif",
".ico": "image/vnd.microsoft.icon",
".jpeg": "image/jpeg",
".jpg": "image/jpeg",
".png": "image/png",
".svg": "image/svg+xml",
".webp": "image/webp",
".woff": "font/woff",
".woff2": "font/woff2",
".mp4": "video/mp4",
".webm": "video/webm",
".zip": "application/zip",
".pdf": "application/pdf"
};
const serveStatic = (options) => {
const dir = resolve(options.dir) + "/";
return async (req, next) => {
if (req.method !== "GET" && req.method !== "HEAD") return next();
const path = new URL(req.url).pathname.slice(1).replace(/\/$/, "");
let paths;
if (path === "") paths = ["index.html"];
else if (extname(path) === "") paths = [`${path}.html`, `${path}/index.html`];
else paths = [path];
for (const path$1 of paths) {
const filePath = join(dir, path$1);
if (!filePath.startsWith(dir)) continue;
const fileStat = await stat(filePath).catch(() => null);
if (fileStat?.isFile()) {
const headers = {
"Content-Length": fileStat.size.toString(),
"Content-Type": COMMON_MIME_TYPES[extname(filePath)] || "application/octet-stream"
};
let stream = createReadStream(filePath);
const acceptEncoding = req.headers.get("accept-encoding") || "";
if (acceptEncoding.includes("br")) {
headers["Content-Encoding"] = "br";
delete headers["Content-Length"];
headers["Vary"] = "Accept-Encoding";
stream = stream.pipe(createBrotliCompress());
} else if (acceptEncoding.includes("gzip")) {
headers["Content-Encoding"] = "gzip";
delete headers["Content-Length"];
headers["Vary"] = "Accept-Encoding";
stream = stream.pipe(createGzip());
}
return new FastResponse(stream, { headers });
}
}
return next();
};
};
//#endregion
export { serveStatic };

2
node_modules/srvx/dist/types.d.mts generated vendored Normal file
View file

@ -0,0 +1,2 @@
import { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTPMiddleware, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, serve } from "./_chunks/types-BtByT9ny.mjs";
export { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTPMiddleware, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, serve };