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

21
node_modules/srvx/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) Pooya Parsa <pooya@pi0.io>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

95
node_modules/srvx/README.md generated vendored Normal file
View file

@ -0,0 +1,95 @@
# λ srvx
<!-- automd:badges color=yellow packagephobia -->
[![npm version](https://img.shields.io/npm/v/srvx?color=yellow)](https://npmjs.com/package/srvx)
[![npm downloads](https://img.shields.io/npm/dm/srvx?color=yellow)](https://npm.chart.dev/srvx)
[![install size](https://badgen.net/packagephobia/install/srvx?color=yellow)](https://packagephobia.com/result?p=srvx)
<!-- /automd -->
Universal Server based on web standards. Works with [Deno](https://deno.com/), [Bun](https://bun.sh/) and [Node.js](https://nodejs.org/en).
- ✅ Zero dependency
- ✅ Full featured CLI with watcher, error handler, serve static and logger
- ✅ Seamless runtime integration with same API ([handler](https://srvx.h3.dev/guide/handler) and [instance](https://srvx.h3.dev/guide/server)).
- ✅ [Node.js compatibility](https://srvx.h3.dev/guide/node) with up to [~96.98%](https://github.com/h3js/srvx/tree/main/test/bench-node) native performance.
- ✅ Zero overhead [Deno](https://deno.com/) and [Bun](https://bun.sh/) support.
## Quick start
```js
export default {
fetch(req: Request) {
return Response.json({ hello: "world!" });
},
};
```
Then, run the server using your favorite runtime:
```bash
# Node.js
$ npx srvx # npm
$ pnpx srvx # pnpm
$ yarn dlx srvx # yarn
# Deno
$ deno -A npm:srvx
# Bun
$ bunx --bun srvx
```
👉 **Visit the 📖 [Documentation](https://srvx.h3.dev/) to learn more.**
## Starter Examples
[➤ Online Playground](https://stackblitz.com/fork/github/h3js/srvx/tree/main/examples/stackblitz?startScript=dev&file=server.mjs)
<!-- automd:examples -->
| Example | Source | Try |
| ---------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
| `elysia` | [examples/elysia](https://github.com/h3js/srvx/tree/main/examples/elysia/) | `npx giget gh:h3js/srvx/examples/elysia srvx-elysia` |
| `express` | [examples/express](https://github.com/h3js/srvx/tree/main/examples/express/) | `npx giget gh:h3js/srvx/examples/express srvx-express` |
| `fastify` | [examples/fastify](https://github.com/h3js/srvx/tree/main/examples/fastify/) | `npx giget gh:h3js/srvx/examples/fastify srvx-fastify` |
| `h3` | [examples/h3](https://github.com/h3js/srvx/tree/main/examples/h3/) | `npx giget gh:h3js/srvx/examples/h3 srvx-h3` |
| `hello-world` | [examples/hello-world](https://github.com/h3js/srvx/tree/main/examples/hello-world/) | `npx giget gh:h3js/srvx/examples/hello-world srvx-hello-world` |
| `hono` | [examples/hono](https://github.com/h3js/srvx/tree/main/examples/hono/) | `npx giget gh:h3js/srvx/examples/hono srvx-hono` |
| `jsx` | [examples/jsx](https://github.com/h3js/srvx/tree/main/examples/jsx/) | `npx giget gh:h3js/srvx/examples/jsx srvx-jsx` |
| `node-handler` | [examples/node-handler](https://github.com/h3js/srvx/tree/main/examples/node-handler/) | `npx giget gh:h3js/srvx/examples/node-handler srvx-node-handler` |
| `service-worker` | [examples/service-worker](https://github.com/h3js/srvx/tree/main/examples/service-worker/) | `npx giget gh:h3js/srvx/examples/service-worker srvx-service-worker` |
| `websocket` | [examples/websocket](https://github.com/h3js/srvx/tree/main/examples/websocket/) | `npx giget gh:h3js/srvx/examples/websocket srvx-websocket` |
<!-- /automd -->
## Contribution
- Clone this repository
- Install the latest LTS version of [Node.js](https://nodejs.org/en/)
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
- Install dependencies using `pnpm install`
- **Prepare stub mode using `pnpm build --stub`**
- Run interactive tests using `pnpm dev`
## License
<!-- automd:contributors author=pi0 license=MIT -->
Published under the [MIT](https://github.com/h3js/srvx/blob/main/LICENSE) license.
Made by [@pi0](https://github.com/pi0) and [community](https://github.com/h3js/srvx/graphs/contributors) 💛
<br><br>
<a href="https://github.com/h3js/srvx/graphs/contributors">
<img src="https://contrib.rocks/image?repo=h3js/srvx" />
</a>
<!-- /automd -->
<!-- automd:with-automd -->
---
_🤖 auto updated with [automd](https://automd.unjs.io)_
<!-- /automd -->

8
node_modules/srvx/bin/srvx.mjs generated vendored Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/env node
import { main } from "../dist/cli.mjs";
await main({
command: "srvx",
docs: "https://srvx.h3.dev",
issues: "https://github.com/h3js/srvx/issues",
});

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 };

93
node_modules/srvx/package.json generated vendored Normal file
View file

@ -0,0 +1,93 @@
{
"name": "srvx",
"version": "0.8.9",
"description": "Universal Server API based on web platform standards. Works seamlessly with Deno, Bun and Node.js.",
"homepage": "https://srvx.h3.dev",
"repository": "h3js/srvx",
"license": "MIT",
"sideEffects": false,
"type": "module",
"exports": {
"./deno": "./dist/adapters/deno.mjs",
"./bun": "./dist/adapters/bun.mjs",
"./node": "./dist/adapters/node.mjs",
"./cloudflare": "./dist/adapters/cloudflare.mjs",
"./generic": "./dist/adapters/generic.mjs",
"./service-worker": "./dist/adapters/service-worker.mjs",
"./cli": "./dist/cli.mjs",
"./static": "./dist/static.mjs",
"./log": "./dist/log.mjs",
".": {
"types": "./dist/types.d.mts",
"deno": "./dist/adapters/deno.mjs",
"bun": "./dist/adapters/bun.mjs",
"workerd": "./dist/adapters/cloudflare.mjs",
"browser": "./dist/adapters/service-worker.mjs",
"node": "./dist/adapters/node.mjs",
"default": "./dist/adapters/generic.mjs"
}
},
"types": "./dist/types.d.mts",
"bin": {
"srvx": "./bin/srvx.mjs"
},
"files": [
"bin",
"dist"
],
"scripts": {
"bench:node": "node test/bench-node/_run.mjs",
"bench:url:bun": "bun run ./test/url.bench.ts",
"bench:url:deno": "deno run -A ./test/url.bench.ts",
"bench:url:node": "pnpm --expose-gc --allow-natives-syntax ./test/url.bench.ts",
"build": "obuild",
"dev": "vitest dev",
"lint": "eslint . && prettier -c .",
"lint:fix": "automd && eslint . --fix && prettier -w .",
"prepack": "pnpm build",
"play:mkcert": "openssl req -x509 -newkey rsa:2048 -nodes -keyout server.key -out server.crt -days 365 -subj /CN=srvx.local",
"release": "pnpm test && changelogen --release && npm publish && git push --follow-tags",
"srvx": "./bin/srvx.mjs",
"test": "pnpm lint && pnpm test:types && vitest run --coverage",
"test:types": "tsc --noEmit --skipLibCheck"
},
"resolutions": {
"srvx": "link:."
},
"dependencies": {
"cookie-es": "^2.0.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20250927.0",
"@hono/node-server": "^1.19.5",
"@mitata/counters": "^0.0.8",
"@mjackson/node-fetch-server": "^0.7.0",
"@types/bun": "^1.2.23",
"@types/deno": "^2.3.0",
"@types/node": "^24.5.2",
"@types/node-forge": "^1.3.14",
"@types/serviceworker": "^0.0.154",
"@vitest/coverage-v8": "^3.2.4",
"@whatwg-node/server": "^0.10.12",
"automd": "^0.4.2",
"changelogen": "^0.6.2",
"eslint": "^9.36.0",
"eslint-config-unjs": "^0.5.0",
"execa": "^9.6.0",
"get-port-please": "^3.2.0",
"mdbox": "^0.1.1",
"mitata": "^1.0.34",
"node-forge": "^1.3.1",
"obuild": "^0.2.1",
"prettier": "^3.6.2",
"srvx-release": "npm:srvx@0.8.8",
"tslib": "^2.8.1",
"typescript": "^5.9.2",
"undici": "^7.16.0",
"vitest": "^3.2.4"
},
"packageManager": "pnpm@10.17.1",
"engines": {
"node": ">=20.16.0"
}
}