feat: init

This commit is contained in:
2026-02-13 22:02:30 +01:00
commit 8f9ff830fb
16711 changed files with 3307340 additions and 0 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.

82
node_modules/srvx/README.md generated vendored Normal file
View File

@@ -0,0 +1,82 @@
# λ 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 a [**close to native performance**](https://github.com/h3js/srvx/tree/main/test/bench-node).
- ✅ 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
```
You can also use `srvx fetch` to directly call your server handler without starting a server:
```bash
$ npx srvx fetch /api/users
```
See [CLI documentation](https://srvx.h3.dev/guide/cli) for more options.
👉 **Visit the 📖 [Documentation](https://srvx.h3.dev/) to learn more.**
## 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 -->

12
node_modules/srvx/bin/srvx.mjs generated vendored Executable file
View File

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

56
node_modules/srvx/dist/_chunks/_plugins.mjs generated vendored Normal file
View File

@@ -0,0 +1,56 @@
import { a as green, i as gray, n as bold, s as red } from "./_utils.mjs";
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));
}
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);
}
});
};
const gracefulShutdownPlugin = (server) => {
const config = server.options?.gracefulShutdown;
if (!globalThis.process?.on || config === false || config === void 0 && (process.env.CI || process.env.TEST)) return;
const gracefulTimeout = config === true || !config?.gracefulTimeout ? Number.parseInt(process.env.SERVER_SHUTDOWN_TIMEOUT || "") || 5 : config.gracefulTimeout;
let isClosing = false;
let isClosed = false;
const w = server.options.silent ? () => {} : process.stderr.write.bind(process.stderr);
const forceClose = async () => {
if (isClosed) return;
w(red("\x1B[2K\rForcibly closing connections...\n"));
isClosed = true;
await server.close(true);
};
const shutdown = async () => {
if (isClosing || isClosed) return;
setTimeout(() => {
globalThis.process.once("SIGINT", forceClose);
}, 100);
isClosing = true;
const closePromise = server.close();
for (let remaining = gracefulTimeout; remaining > 0; remaining--) {
w(gray(`\rStopping server gracefully (${remaining}s)... Press ${bold("Ctrl+C")} again to force close.`));
if (await Promise.race([closePromise.then(() => true), new Promise((r) => setTimeout(() => r(false), 1e3))])) {
w("\x1B[2K\r" + green("Server closed successfully.\n"));
isClosed = true;
return;
}
}
w("\x1B[2K\rGraceful shutdown timed out.\n");
await forceClose();
};
for (const sig of ["SIGINT", "SIGTERM"]) globalThis.process.on(sig, shutdown);
};
export { gracefulShutdownPlugin as n, wrapFetch as r, errorPlugin as t };

28
node_modules/srvx/dist/_chunks/_url.d.mts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
//#region src/_url.d.ts
type URLInit = {
protocol: string;
host: string;
pathname: string;
search: string;
};
/**
* URL wrapper with fast paths to access to the following props:
*
* - `url.pathname`
* - `url.search`
* - `url.searchParams`
* - `url.protocol`
*
* **NOTES:**
*
* - It is assumed that the input URL is **already encoded** and formatted from an HTTP request and contains no hash.
* - Triggering the setters or getters on other props will deoptimize to full URL parsing.
* - Changes to `searchParams` will be discarded as we don't track them.
*/
declare const FastURL: {
new (url: string | URLInit): URL & {
_url: URL;
};
};
//#endregion
export { FastURL as t };

126
node_modules/srvx/dist/_chunks/_url.mjs generated vendored Normal file
View File

@@ -0,0 +1,126 @@
function lazyInherit(target, source, sourceKey) {
for (const key of [...Object.getOwnPropertyNames(source), ...Object.getOwnPropertySymbols(source)]) {
if (key === "constructor") continue;
const targetDesc = Object.getOwnPropertyDescriptor(target, key);
const desc = Object.getOwnPropertyDescriptor(source, key);
let modified = false;
if (desc.get) {
modified = true;
desc.get = targetDesc?.get || function() {
return this[sourceKey][key];
};
}
if (desc.set) {
modified = true;
desc.set = targetDesc?.set || function(value) {
this[sourceKey][key] = value;
};
}
if (!targetDesc?.value && typeof desc.value === "function") {
modified = true;
desc.value = function(...args) {
return this[sourceKey][key](...args);
};
}
if (modified) Object.defineProperty(target, key, desc);
}
}
const FastURL = /* @__PURE__ */ (() => {
const NativeURL = globalThis.URL;
const FastURL = class URL {
#url;
#href;
#protocol;
#host;
#pathname;
#search;
#searchParams;
#pos;
constructor(url) {
if (typeof url === "string") this.#href = url;
else {
this.#protocol = url.protocol;
this.#host = url.host;
this.#pathname = url.pathname;
this.#search = url.search;
}
}
static [Symbol.hasInstance](val) {
return val instanceof NativeURL;
}
get _url() {
if (this.#url) return this.#url;
this.#url = new NativeURL(this.href);
this.#href = void 0;
this.#protocol = void 0;
this.#host = void 0;
this.#pathname = void 0;
this.#search = void 0;
this.#searchParams = void 0;
this.#pos = void 0;
return this.#url;
}
get href() {
if (this.#url) return this.#url.href;
if (!this.#href) this.#href = `${this.#protocol || "http:"}//${this.#host || "localhost"}${this.#pathname || "/"}${this.#search || ""}`;
return this.#href;
}
#getPos() {
if (!this.#pos) {
const url = this.href;
const protoIndex = url.indexOf("://");
const pathnameIndex = protoIndex === -1 ? -1 : url.indexOf("/", protoIndex + 4);
this.#pos = [
protoIndex,
pathnameIndex,
pathnameIndex === -1 ? -1 : url.indexOf("?", pathnameIndex)
];
}
return this.#pos;
}
get pathname() {
if (this.#url) return this.#url.pathname;
if (this.#pathname === void 0) {
const [, pathnameIndex, queryIndex] = this.#getPos();
if (pathnameIndex === -1) return this._url.pathname;
this.#pathname = this.href.slice(pathnameIndex, queryIndex === -1 ? void 0 : queryIndex);
}
return this.#pathname;
}
get search() {
if (this.#url) return this.#url.search;
if (this.#search === void 0) {
const [, pathnameIndex, queryIndex] = this.#getPos();
if (pathnameIndex === -1) return this._url.search;
const url = this.href;
this.#search = queryIndex === -1 || queryIndex === url.length - 1 ? "" : url.slice(queryIndex);
}
return this.#search;
}
get searchParams() {
if (this.#url) return this.#url.searchParams;
if (!this.#searchParams) this.#searchParams = new URLSearchParams(this.search);
return this.#searchParams;
}
get protocol() {
if (this.#url) return this.#url.protocol;
if (this.#protocol === void 0) {
const [protocolIndex] = this.#getPos();
if (protocolIndex === -1) return this._url.protocol;
this.#protocol = this.href.slice(0, protocolIndex + 1);
}
return this.#protocol;
}
toString() {
return this.href;
}
toJSON() {
return this.href;
}
};
lazyInherit(FastURL.prototype, NativeURL.prototype, "_url");
Object.setPrototypeOf(FastURL.prototype, NativeURL.prototype);
Object.setPrototypeOf(FastURL, NativeURL);
return FastURL;
})();
export { lazyInherit as n, FastURL as t };

15
node_modules/srvx/dist/_chunks/_utils.mjs generated vendored Normal file
View File

@@ -0,0 +1,15 @@
const noColor = /* @__PURE__ */ (() => {
const env = globalThis.process?.env ?? {};
return env.NO_COLOR === "1" || env.TERM === "dumb";
})();
const _c = (c, r = 39) => (t) => noColor ? t : `\u001B[${c}m${t}\u001B[${r}m`;
const bold = /* @__PURE__ */ _c(1, 22);
const red = /* @__PURE__ */ _c(31);
const green = /* @__PURE__ */ _c(32);
const yellow = /* @__PURE__ */ _c(33);
const blue = /* @__PURE__ */ _c(34);
const magenta = /* @__PURE__ */ _c(35);
const cyan = /* @__PURE__ */ _c(36);
const gray = /* @__PURE__ */ _c(90);
const url = (title, url) => noColor ? `[${title}](${url})` : `\u001B]8;;${url}\u001B\\${title}\u001B]8;;\u001B\\`;
export { green as a, url as c, gray as i, yellow as l, bold as n, magenta as o, cyan as r, red as s, blue as t };

70
node_modules/srvx/dist/_chunks/_utils2.mjs generated vendored Normal file
View File

@@ -0,0 +1,70 @@
function resolvePortAndHost(opts) {
const _port = opts.port ?? globalThis.process?.env.PORT ?? 3e3;
const port = typeof _port === "number" ? _port : Number.parseInt(_port, 10);
if (port < 0 || port > 65535) throw new RangeError(`Port must be between 0 and 65535 (got "${port}").`);
return {
port,
hostname: opts.hostname ?? globalThis.process?.env.HOST
};
}
function fmtURL(host, port, secure) {
if (!host || !port) return;
if (host.includes(":")) host = `[${host}]`;
return `http${secure ? "s" : ""}://${host}:${port}/`;
}
function printListening(opts, url) {
if (!url || (opts.silent ?? globalThis.process?.env?.TEST)) return;
let additionalInfo = "";
try {
const _url = new URL(url);
if (_url.hostname === "[::]" || _url.hostname === "0.0.0.0") {
_url.hostname = "localhost";
url = _url.href;
additionalInfo = " (all interfaces)";
}
} catch {}
let listeningOn = `➜ Listening on:`;
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 = /* @__PURE__ */ new Set();
return {
waitUntil: (promise) => {
if (typeof promise?.then !== "function") return;
promises.add(Promise.resolve(promise).catch(console.error).finally(() => {
promises.delete(promise);
}));
},
wait: () => {
return Promise.all(promises);
}
};
}
export { resolveTLSOptions as a, resolvePortAndHost as i, fmtURL as n, printListening as r, createWaitUntil as t };

19
node_modules/srvx/dist/adapters/aws-lambda.d.mts generated vendored Normal file
View File

@@ -0,0 +1,19 @@
import { FetchHandler, ServerOptions } from "../types.mjs";
import * as AWS from "aws-lambda";
//#region src/adapters/_aws/utils.d.ts
type AWSLambdaResponseStream = NodeJS.WritableStream & {
setContentType(contentType: string): void;
};
//#endregion
//#region src/adapters/aws-lambda.d.ts
type MaybePromise<T> = T | Promise<T>;
type AwsLambdaEvent = AWS.APIGatewayProxyEvent | AWS.APIGatewayProxyEventV2;
type AWSLambdaHandler = (event: AwsLambdaEvent, context: AWS.Context) => MaybePromise<AWS.APIGatewayProxyResult | AWS.APIGatewayProxyResultV2>;
type AWSLambdaStreamingHandler = (event: AwsLambdaEvent, responseStream: AWSLambdaResponseStream, context: AWS.Context) => MaybePromise<void>;
declare function toLambdaHandler(options: ServerOptions): AWSLambdaHandler;
declare function handleLambdaEvent(fetchHandler: FetchHandler, event: AwsLambdaEvent, context: AWS.Context): Promise<AWS.APIGatewayProxyResult | AWS.APIGatewayProxyResultV2>;
declare function handleLambdaEventWithStream(fetchHandler: FetchHandler, event: AwsLambdaEvent, responseStream: AWSLambdaResponseStream, context: AWS.Context): Promise<void>;
declare function invokeLambdaHandler(handler: AWSLambdaHandler, request: Request): Promise<Response>;
//#endregion
export { AWSLambdaHandler, type AWSLambdaResponseStream, AWSLambdaStreamingHandler, AwsLambdaEvent, handleLambdaEvent, handleLambdaEventWithStream, invokeLambdaHandler, toLambdaHandler };

292
node_modules/srvx/dist/adapters/aws-lambda.mjs generated vendored Normal file
View File

@@ -0,0 +1,292 @@
import { r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
function awsRequest(event, context) {
const req = new Request(awsEventURL(event), {
method: awsEventMethod(event),
headers: awsEventHeaders(event),
body: awsEventBody(event)
});
req.runtime = {
name: "aws-lambda",
awsLambda: {
event,
context
}
};
req.ip = awsEventIP(event);
return req;
}
function awsEventMethod(event) {
return event.httpMethod || event.requestContext?.http?.method || "GET";
}
function awsEventIP(event) {
return event.requestContext?.http?.sourceIp || event.requestContext?.identity?.sourceIp;
}
function awsEventURL(event) {
const hostname = event.headers.host || event.headers.Host || event.requestContext?.domainName || ".";
const path = event.path || event.rawPath;
const query = awsEventQuery(event);
const protocol = (event.headers["X-Forwarded-Proto"] || event.headers["x-forwarded-proto"]) === "http" ? "http" : "https";
return new URL(`${path}${query ? `?${query}` : ""}`, `${protocol}://${hostname}`);
}
function awsEventQuery(event) {
if (typeof event.rawQueryString === "string") return event.rawQueryString;
return stringifyQuery({
...event.queryStringParameters,
...event.multiValueQueryStringParameters
});
}
function awsEventHeaders(event) {
const headers = new Headers();
for (const [key, value] of Object.entries(event.headers)) if (value) headers.set(key, value);
if ("cookies" in event && event.cookies) for (const cookie of event.cookies) headers.append("cookie", cookie);
return headers;
}
function awsEventBody(event) {
if (!event.body) return;
if (event.isBase64Encoded) return Buffer.from(event.body || "", "base64");
return event.body;
}
function awsResponseHeaders(response, event) {
const headers = Object.create(null);
for (const [key, value] of response.headers) if (value) headers[key] = Array.isArray(value) ? value.join(",") : String(value);
const cookies = response.headers.getSetCookie();
if (cookies.length === 0) return { headers };
return event?.version === "2.0" || !!event?.requestContext?.http ? {
headers,
cookies
} : {
headers,
cookies,
multiValueHeaders: { "set-cookie": cookies }
};
}
async function awsResponseBody(response) {
if (!response.body) return { body: "" };
const buffer = await toBuffer(response.body);
return isTextType(response.headers.get("content-type") || "") ? { body: buffer.toString("utf8") } : {
body: buffer.toString("base64"),
isBase64Encoded: true
};
}
async function awsStreamResponse(response, responseStream, event) {
const metadata = {
statusCode: response.status,
...awsResponseHeaders(response, event)
};
if (!metadata.headers["transfer-encoding"]) metadata.headers["transfer-encoding"] = "chunked";
const writer = globalThis.awslambda.HttpResponseStream.from(responseStream, metadata);
if (!response.body) {
writer.end();
return;
}
try {
await streamToNodeStream(response.body, writer);
} finally {
writer.end();
}
}
async function streamToNodeStream(body, writer) {
const reader = body.getReader();
try {
let result = await reader.read();
while (!result.done) {
if (!writer.write(result.value)) await new Promise((resolve) => writer.once("drain", resolve));
result = await reader.read();
}
} finally {
reader.releaseLock();
}
}
function isTextType(contentType = "") {
return /^text\/|\/(javascript|json|xml)|utf-?8/i.test(contentType);
}
function toBuffer(data) {
return new Promise((resolve, reject) => {
const chunks = [];
data.pipeTo(new WritableStream({
write(chunk) {
chunks.push(chunk);
},
close() {
resolve(Buffer.concat(chunks));
},
abort(reason) {
reject(reason);
}
})).catch(reject);
});
}
function stringifyQuery(obj) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(obj)) {
if (value == null) continue;
if (Array.isArray(value)) for (const v of value) params.append(key, String(v));
else params.append(key, String(value));
}
return params.toString();
}
async function requestToAwsEvent(request) {
const url = new URL(request.url);
const headers = {};
const cookies = [];
for (const [key, value] of request.headers) {
if (key.toLowerCase() === "cookie") cookies.push(value);
headers[key] = value;
}
let body;
let isBase64Encoded = false;
if (request.body) {
const buffer = await toBuffer(request.body);
if (isTextType(request.headers.get("content-type") || "")) body = buffer.toString("utf8");
else {
body = buffer.toString("base64");
isBase64Encoded = true;
}
}
const now = Date.now();
return {
httpMethod: request.method,
path: url.pathname,
resource: url.pathname,
queryStringParameters: Object.fromEntries(url.searchParams),
multiValueQueryStringParameters: parseMultiValueQuery(url.searchParams),
pathParameters: void 0,
stageVariables: void 0,
multiValueHeaders: Object.fromEntries([...request.headers].map(([k, v]) => [k, [v]])),
version: "2.0",
rawPath: url.pathname,
rawQueryString: url.search.slice(1),
cookies: cookies.length > 0 ? cookies : void 0,
routeKey: `${request.method} ${url.pathname}`,
headers,
body: body ?? null,
isBase64Encoded,
requestContext: {
accountId: "000000000000",
apiId: "local",
resourceId: "local",
stage: "$default",
requestId: crypto.randomUUID(),
identity: {
sourceIp: "127.0.0.1",
userAgent: request.headers.get("user-agent") || "",
accessKey: null,
accountId: null,
apiKey: null,
apiKeyId: null,
caller: null,
clientCert: null,
cognitoAuthenticationProvider: null,
cognitoAuthenticationType: null,
cognitoIdentityId: null,
cognitoIdentityPoolId: null,
principalOrgId: null,
user: null,
userArn: null
},
resourcePath: url.pathname,
httpMethod: request.method,
path: url.pathname,
protocol: "HTTP/1.1",
requestTimeEpoch: now,
authorizer: void 0,
domainName: url.hostname,
http: {
method: request.method,
path: url.pathname,
protocol: "HTTP/1.1",
sourceIp: "127.0.0.1",
userAgent: request.headers.get("user-agent") || ""
},
routeKey: `${request.method} ${url.pathname}`,
time: new Date(now).toISOString(),
timeEpoch: now,
domainPrefix: url.hostname.split(".")[0]
}
};
}
function parseMultiValueQuery(params) {
const result = {};
for (const [key, value] of params) {
if (!result[key]) result[key] = [];
result[key].push(value);
}
return result;
}
function awsResultToResponse(result) {
if (typeof result === "string") return new Response(result, { status: 200 });
const headers = new Headers();
if (result.headers) {
for (const [key, value] of Object.entries(result.headers)) if (value !== void 0) headers.set(key, String(value));
}
if ("multiValueHeaders" in result && result.multiValueHeaders) {
for (const [key, values] of Object.entries(result.multiValueHeaders)) if (values) for (const value of values) headers.append(key, String(value));
}
if ("cookies" in result && result.cookies) for (const cookie of result.cookies) headers.append("set-cookie", cookie);
let body;
if (typeof result.body === "string") if (result.isBase64Encoded) body = Buffer.from(result.body, "base64");
else body = result.body;
const statusCode = typeof result.statusCode === "number" ? result.statusCode : 200;
return new Response(body, {
status: statusCode,
headers
});
}
function createMockContext() {
const id = crypto.randomUUID();
return {
callbackWaitsForEmptyEventLoop: true,
functionName: "local",
functionVersion: "$LATEST",
invokedFunctionArn: `arn:aws:lambda:us-east-1:000000000000:function:local`,
memoryLimitInMB: "128",
awsRequestId: id,
logGroupName: "/aws/lambda/local",
logStreamName: `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}/[$LATEST]${id}`,
getRemainingTimeInMillis: () => 3e4,
done: () => {},
fail: () => {},
succeed: () => {}
};
}
function toLambdaHandler(options) {
const server = new AWSLambdaServer(options);
return (event, context) => server.fetch(event, context);
}
async function handleLambdaEvent(fetchHandler, event, context) {
const response = await fetchHandler(awsRequest(event, context));
return {
statusCode: response.status,
...awsResponseHeaders(response, event),
...await awsResponseBody(response)
};
}
async function handleLambdaEventWithStream(fetchHandler, event, responseStream, context) {
await awsStreamResponse(await fetchHandler(awsRequest(event, context)), responseStream, event);
}
async function invokeLambdaHandler(handler, request) {
return awsResultToResponse(await handler(await requestToAwsEvent(request), createMockContext()));
}
var AWSLambdaServer = class {
runtime = "aws-lambda";
options;
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 = (event, context) => handleLambdaEvent(fetchHandler, event, context);
}
serve() {}
ready() {
return Promise.resolve().then(() => this);
}
close() {
return Promise.resolve();
}
};
export { handleLambdaEvent, handleLambdaEventWithStream, invokeLambdaHandler, toLambdaHandler };

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

@@ -0,0 +1,22 @@
import { BunFetchHandler, Server, ServerOptions } from "../types.mjs";
import { t as FastURL } from "../_chunks/_url.mjs";
import * as bun from "bun";
//#region src/adapters/bun.d.ts
declare const FastResponse: typeof globalThis.Response;
declare function serve(options: ServerOptions): BunServer;
declare class BunServer implements Server<BunFetchHandler> {
#private;
readonly runtime = "bun";
readonly options: Server["options"];
readonly bun: Server["bun"];
readonly serveOptions: bun.Serve.Options<any> | undefined;
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 };

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

@@ -0,0 +1,84 @@
import { t as FastURL } from "../_chunks/_url.mjs";
import { a as resolveTLSOptions, i as resolvePortAndHost, n as fmtURL, r as printListening, t as createWaitUntil } from "../_chunks/_utils2.mjs";
import { n as gracefulShutdownPlugin, r as wrapFetch } from "../_chunks/_plugins.mjs";
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);
gracefulShutdownPlugin(this);
const fetchHandler = wrapFetch(this);
const loader = globalThis.__srvxLoader__;
if (loader) {
this.fetch = fetchHandler;
loader(fetchHandler);
return;
}
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))]);
}
};
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 "../types.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 };

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

@@ -0,0 +1,57 @@
import { r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
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();
}
};
export { FastResponse, FastURL, serve };

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

@@ -0,0 +1,21 @@
import { DenoFetchHandler, Server, ServerOptions } from "../types.mjs";
import { t as FastURL } from "../_chunks/_url.mjs";
//#region src/adapters/deno.d.ts
declare const FastResponse: typeof globalThis.Response;
declare function serve(options: ServerOptions): DenoServer;
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) | undefined;
readonly fetch: DenoFetchHandler;
constructor(options: ServerOptions);
serve(): Promise<this>;
get url(): string | undefined;
ready(): Promise<Server>;
close(): Promise<void>;
}
//#endregion
export { FastResponse, FastURL, serve };

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

@@ -0,0 +1,93 @@
import { t as FastURL } from "../_chunks/_url.mjs";
import { a as resolveTLSOptions, i as resolvePortAndHost, n as fmtURL, r as printListening, t as createWaitUntil } from "../_chunks/_utils2.mjs";
import { n as gracefulShutdownPlugin, r as wrapFetch } from "../_chunks/_plugins.mjs";
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);
gracefulShutdownPlugin(this);
const fetchHandler = wrapFetch(this);
const loader = globalThis.__srvxLoader__;
if (loader) {
this.fetch = fetchHandler;
loader(fetchHandler);
return;
}
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())]);
}
};
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 "../types.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 };

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

@@ -0,0 +1,35 @@
import { t as createWaitUntil } from "../_chunks/_utils2.mjs";
import { r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
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();
}
};
export { FastResponse, FastURL, serve };

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

@@ -0,0 +1,78 @@
import { FetchHandler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerOptions, ServerRequest } from "../types.mjs";
import { t as FastURL } from "../_chunks/_url.mjs";
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;
};
/**
* Undici uses an incompatible Request constructor depending on private property accessors.
*
* This utility, patches global Request to support `new Request(req)` in Node.js.
*
* Alternatively you can use `new Request(req._request || req)` instead of patching global Request.
*/
declare function patchGlobalRequest(): typeof Request;
//#endregion
//#region src/adapters/_node/response.d.ts
type PreparedNodeResponseBody = string | Buffer | Uint8Array | DataView | ReadableStream | Readable | undefined | null;
interface PreparedNodeResponse {
status: number;
statusText: string;
headers: [string, string][];
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 & {
_toNodeResponse: () => 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/web/fetch.d.ts
/**
* Calls a Node.js HTTP Request handler with a Fetch API Request object and returns a Response object.
*
* If the web Request contains an existing Node.js req/res pair (indicating it originated from a Node.js server from srvx/node), it will be called directly.
*
* Otherwise, new Node.js IncomingMessage and ServerResponse objects are created and linked to a custom Duplex stream that bridges the Fetch API streams with Node.js streams.
*
* The handler is invoked with these objects, and the response is constructed from the ServerResponse once it is finished.
*
* @experimental Behavior might be unstable.
*/
declare function fetchNodeHandler(handler: NodeHttpHandler, req: ServerRequest): Promise<Response>;
//#endregion
//#region src/adapters/_node/adapter.d.ts
type AdapterMeta = {
__nodeHandler?: NodeHttpHandler;
__fetchHandler?: FetchHandler;
};
/**
* Converts a Fetch API handler to a Node.js HTTP handler.
*/
declare function toNodeHandler(handler: FetchHandler & AdapterMeta): NodeHttpHandler & AdapterMeta;
/**
* Converts a Node.js HTTP handler into a Fetch API handler.
*
* @experimental Behavior might be unstable and won't work in Bun and Deno currently (tracker: https://github.com/h3js/srvx/issues/132)
*/
declare function toFetchHandler(handler: NodeHttpHandler & AdapterMeta): FetchHandler & AdapterMeta;
//#endregion
//#region src/adapters/node.d.ts
declare function serve(options: ServerOptions): Server;
//#endregion
export { type AdapterMeta, NodeResponse as FastResponse, NodeResponse, FastURL, NodeRequest, fetchNodeHandler, patchGlobalRequest, sendNodeResponse, serve, toFetchHandler, toNodeHandler };

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

@@ -0,0 +1,744 @@
import { n as lazyInherit, t as FastURL } from "../_chunks/_url.mjs";
import { a as resolveTLSOptions, i as resolvePortAndHost, n as fmtURL, r as printListening, t as createWaitUntil } from "../_chunks/_utils2.mjs";
import { n as gracefulShutdownPlugin, r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
import nodeHTTP, { IncomingMessage, ServerResponse } from "node:http";
import { Duplex, PassThrough, Readable } from "node:stream";
import nodeHTTPS from "node:https";
import nodeHTTP2 from "node:http2";
async function sendNodeResponse(nodeRes, webRes) {
if (!webRes) {
nodeRes.statusCode = 500;
return endNodeResponse(nodeRes);
}
if (webRes._toNodeResponse) {
const res = webRes._toNodeResponse();
writeHead(nodeRes, res.status, res.statusText, res.headers);
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 rawHeaders = [...webRes.headers];
writeHead(nodeRes, webRes.status, webRes.statusText, rawHeaders);
return webRes.body ? streamBody(webRes.body, nodeRes) : endNodeResponse(nodeRes);
}
function writeHead(nodeRes, status, statusText, rawHeaders) {
const writeHeaders = globalThis.Deno ? rawHeaders : rawHeaders.flat();
if (!nodeRes.headersSent) if (nodeRes.req?.httpVersion === "2.0") nodeRes.writeHead(status, writeHeaders);
else nodeRes.writeHead(status, statusText, writeHeaders);
}
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.catch(streamCancel).finally(() => {
nodeRes.off("close", streamCancel);
nodeRes.off("error", streamCancel);
});
}
var NodeRequestURL = class extends FastURL {
#req;
constructor({ req }) {
const path = req.url || "/";
if (path[0] === "/") {
const qIndex = path.indexOf("?");
const pathname = qIndex === -1 ? path : path?.slice(0, qIndex) || "/";
const search = qIndex === -1 ? "" : path?.slice(qIndex) || "";
const host = req.headers.host || req.headers[":authority"] || `${req.socket.localFamily === "IPv6" ? "[" + req.socket.localAddress + "]" : req.socket.localAddress}:${req.socket?.localPort || "80"}`;
const protocol = req.socket?.encrypted || req.headers["x-forwarded-proto"] === "https" || req.headers[":scheme"] === "https" ? "https:" : "http:";
super({
protocol,
host,
pathname,
search
});
} else super(path);
this.#req = req;
}
get pathname() {
return super.pathname;
}
set pathname(value) {
this._url.pathname = value;
this.#req.url = this._url.pathname + this._url.search;
}
};
const NodeRequestHeaders = /* @__PURE__ */ (() => {
const NativeHeaders = globalThis.Headers;
class Headers {
#req;
#headers;
constructor(req) {
this.#req = req;
}
static [Symbol.hasInstance](val) {
return val instanceof NativeHeaders;
}
get _headers() {
if (!this.#headers) {
const headers = new NativeHeaders();
const rawHeaders = this.#req.rawHeaders;
const len = rawHeaders.length;
for (let i = 0; i < len; i += 2) {
const key = rawHeaders[i];
if (key.charCodeAt(0) === 58) continue;
const value = rawHeaders[i + 1];
headers.append(key, value);
}
this.#headers = headers;
}
return this.#headers;
}
get(name) {
if (this.#headers) return this.#headers.get(name);
const value = this.#req.headers[name.toLowerCase()];
return Array.isArray(value) ? value.join(", ") : value || null;
}
has(name) {
if (this.#headers) return this.#headers.has(name);
return name.toLowerCase() in this.#req.headers;
}
getSetCookie() {
if (this.#headers) return this.#headers.getSetCookie();
const value = this.#req.headers["set-cookie"];
return Array.isArray(value) ? value : value ? [value] : [];
}
*_entries() {
const rawHeaders = this.#req.rawHeaders;
const len = rawHeaders.length;
for (let i = 0; i < len; i += 2) {
const key = rawHeaders[i];
if (key.charCodeAt(0) === 58) continue;
yield [key.toLowerCase(), rawHeaders[i + 1]];
}
}
entries() {
return this.#headers ? this.#headers.entries() : this._entries();
}
[Symbol.iterator]() {
return this.entries();
}
}
lazyInherit(Headers.prototype, NativeHeaders.prototype, "_headers");
Object.setPrototypeOf(Headers, NativeHeaders);
Object.setPrototypeOf(Headers.prototype, NativeHeaders.prototype);
return Headers;
})();
const NodeRequest = /* @__PURE__ */ (() => {
const NativeRequest = globalThis.Request;
class Request {
runtime;
#req;
#url;
#bodyStream;
#request;
#headers;
#abortController;
constructor(ctx) {
this.#req = ctx.req;
this.runtime = {
name: "node",
node: ctx
};
}
static [Symbol.hasInstance](val) {
return val instanceof NativeRequest;
}
get ip() {
return this.#req.socket?.remoteAddress;
}
get method() {
if (this.#request) return this.#request.method;
return this.#req.method || "GET";
}
get _url() {
return this.#url ||= new NodeRequestURL({ req: this.#req });
}
set _url(url) {
this.#url = url;
}
get url() {
if (this.#request) return this.#request.url;
return this._url.href;
}
get headers() {
if (this.#request) return this.#request.headers;
return this.#headers ||= new NodeRequestHeaders(this.#req);
}
get _abortController() {
if (!this.#abortController) {
this.#abortController = new AbortController();
const { req, res } = this.runtime.node;
const abortController = this.#abortController;
const abort = (err) => abortController.abort?.(err);
if (res) res.once("close", () => {
const reqError = req.errored;
if (reqError) abort(reqError);
else if (!res.writableEnded) abort();
});
else req.once("close", () => {
if (!req.complete) abort();
});
}
return this.#abortController;
}
get signal() {
return this.#request ? this.#request.signal : this._abortController.signal;
}
get body() {
if (this.#request) return this.#request.body;
if (this.#bodyStream === void 0) {
const method = this.method;
this.#bodyStream = !(method === "GET" || method === "HEAD") ? Readable.toWeb(this.#req) : null;
}
return this.#bodyStream;
}
text() {
if (this.#request) return this.#request.text();
if (this.#bodyStream !== void 0) return this.#bodyStream ? new Response(this.#bodyStream).text() : Promise.resolve("");
return readBody(this.#req).then((buf) => buf.toString());
}
json() {
if (this.#request) return this.#request.json();
return this.text().then((text) => JSON.parse(text));
}
get _request() {
if (!this.#request) {
const body = this.body;
this.#request = new NativeRequest(this.url, {
method: this.method,
headers: this.headers,
signal: this._abortController.signal,
body,
duplex: body ? "half" : void 0
});
this.#headers = void 0;
this.#bodyStream = void 0;
}
return this.#request;
}
}
lazyInherit(Request.prototype, NativeRequest.prototype, "_request");
Object.setPrototypeOf(Request.prototype, NativeRequest.prototype);
return Request;
})();
function patchGlobalRequest() {
const NativeRequest = globalThis[Symbol.for("srvx.nativeRequest")] ??= globalThis.Request;
const PatchedRequest = class Request extends NativeRequest {
static _srvx = true;
static [Symbol.hasInstance](instance) {
if (this === PatchedRequest) return instance instanceof NativeRequest;
else return Object.prototype.isPrototypeOf.call(this.prototype, instance);
}
constructor(input, options) {
if (typeof input === "object" && "_request" in input) input = input._request;
super(input, options);
}
};
if (!globalThis.Request._srvx) globalThis.Request = PatchedRequest;
return PatchedRequest;
}
function readBody(req) {
if ("rawBody" in req && Buffer.isBuffer(req.rawBody)) return Promise.resolve(req.rawBody);
return new Promise((resolve, reject) => {
const chunks = [];
const onData = (chunk) => {
chunks.push(chunk);
};
const onError = (err) => {
reject(err);
};
const onEnd = () => {
req.off("error", onError);
req.off("data", onData);
resolve(Buffer.concat(chunks));
};
req.on("data", onData).once("end", onEnd).once("error", onError);
});
}
const NodeResponse = /* @__PURE__ */ (() => {
const NativeResponse = globalThis.Response;
const STATUS_CODES = globalThis.process?.getBuiltinModule?.("node:http")?.STATUS_CODES || {};
class NodeResponse {
#body;
#init;
#headers;
#response;
constructor(body, init) {
this.#body = body;
this.#init = init;
}
static [Symbol.hasInstance](val) {
return val instanceof NativeResponse;
}
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;
let body = this.#body;
if (body && typeof body.pipe === "function" && !(body instanceof Readable)) {
const stream = new PassThrough();
body.pipe(stream);
const abort = body.abort;
if (abort) stream.once("close", () => abort());
body = stream;
}
this.#response = new NativeResponse(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;
}
_toNodeResponse() {
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 headers = [];
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 (Array.isArray(value)) for (const v of value) headers.push([key, v]);
else headers.push([key, value]);
if (key === "content-type") hasContentTypeHeader = true;
else if (key === "content-length") hasContentLength = true;
}
if (contentType && !hasContentTypeHeader) headers.push(["content-type", contentType]);
if (contentLength && !hasContentLength) headers.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,
body
};
}
}
lazyInherit(NodeResponse.prototype, NativeResponse.prototype, "_response");
Object.setPrototypeOf(NodeResponse, NativeResponse);
Object.setPrototypeOf(NodeResponse.prototype, NativeResponse.prototype);
return NodeResponse;
})();
var WebRequestSocket = class extends Duplex {
_httpMessage;
autoSelectFamilyAttemptedAddresses = [];
bufferSize = 0;
bytesRead = 0;
bytesWritten = 0;
connecting = false;
pending = false;
readyState = "open";
remoteAddress = "";
remoteFamily = "";
remotePort = 0;
#request;
#timeoutTimer;
#reqReader;
#headersWritten;
#_writeBody;
_webResBody;
constructor(request) {
super({
signal: request.signal,
allowHalfOpen: true
});
this.#request = request;
this._webResBody = new ReadableStream({ start: (controller) => {
this.#_writeBody = controller.enqueue.bind(controller);
this.once("finish", () => {
this.readyState = "closed";
controller.close();
});
} });
}
setTimeout(ms, cb) {
if (typeof ms !== "number" || !Number.isFinite(ms) || ms < 0) return this;
if (cb) this.on("timeout", cb);
if (this.#timeoutTimer) clearTimeout(this.#timeoutTimer);
if (ms > 0) this.#timeoutTimer = setTimeout(() => this.emit("timeout"), ms);
return this;
}
setNoDelay() {
return this;
}
setKeepAlive() {
return this;
}
ref() {
return this;
}
unref() {
return this;
}
destroySoon() {
this.destroy();
}
connect() {
return this;
}
resetAndDestroy() {
this.destroy();
return this;
}
address() {
return {
address: "",
family: "",
port: 0
};
}
_read(_size) {
const reader = this.#reqReader ??= this.#request.body?.getReader();
if (!reader) {
this.push(null);
return;
}
reader.read().then((res) => this._onRead(res)).catch((error) => {
this.emit("error", error);
});
}
_onRead(res) {
if (res.done) {
this.push(null);
return;
}
if (res.value) {
this.bytesRead += res.value.byteLength;
this.push(res.value);
}
}
_write(chunk, encoding, callback) {
if (this.#headersWritten) this.#_writeBody(typeof chunk === "string" ? Buffer.from(chunk, encoding) : chunk);
else if (chunk?.length > 0) {
this.#headersWritten = true;
const headerEnd = chunk.lastIndexOf("\r\n\r\n");
if (headerEnd === -1) throw new Error("Invalid HTTP headers chunk!");
if (headerEnd < chunk.length - 4) {
this._write(chunk.slice(headerEnd + 4), encoding, () => {
callback(null);
});
return;
}
}
callback(null);
}
_final(callback) {
callback(null);
}
_destroy(err, cb) {
if (this.#timeoutTimer) clearTimeout(this.#timeoutTimer);
if (this.#reqReader) this.#reqReader.cancel().catch((error) => {
console.error(error);
});
this.readyState = "closed";
cb(err ?? void 0);
}
};
var WebIncomingMessage = class extends IncomingMessage {
constructor(req, socket) {
super(socket);
this.method = req.method;
const url = req._url ??= new FastURL(req.url);
this.url = url.pathname + url.search;
for (const [key, value] of req.headers.entries()) this.headers[key.toLowerCase()] = value;
if (req.method !== "GET" && req.method !== "HEAD" && !this.headers["content-length"] && !this.headers["transfer-encoding"]) this.headers["transfer-encoding"] = "chunked";
const onData = (chunk) => {
this.push(chunk);
};
socket.on("data", onData);
socket.once("end", () => {
this.emit("end");
this.off("data", onData);
});
}
};
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) {
const headerEntries = [];
const rawHeaders = nodeRes.getHeaders();
for (const [name, value] of Object.entries(rawHeaders)) if (Array.isArray(value)) for (const v of value) headerEntries.push([name, v]);
else if (value) headerEntries.push([name, String(value)]);
_headers = new Headers(headerEntries);
}
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) => {
stream.once("end", () => resolve(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);
}
});
}
var WebServerResponse = class extends ServerResponse {
#socket;
constructor(req, socket) {
super(req);
this.assignSocket(socket);
this.once("finish", () => {
socket.end();
});
this.#socket = socket;
this.waitToFinish = this.waitToFinish.bind(this);
this.toWebResponse = this.toWebResponse.bind(this);
}
waitToFinish() {
if (this.writableEnded) return Promise.resolve();
return new Promise((resolve, reject) => {
this.on("finish", () => resolve());
this.on("error", (err) => reject(err));
});
}
async toWebResponse() {
await this.waitToFinish();
const headers = [];
const httpHeader = this._header?.split("\r\n");
for (let i = 1; httpHeader && i < httpHeader.length; i++) {
const sepIndex = httpHeader[i].indexOf(": ");
if (sepIndex === -1) continue;
const key = httpHeader[i].slice(0, Math.max(0, sepIndex));
const value = httpHeader[i].slice(Math.max(0, sepIndex + 2));
if (!key) continue;
headers.push([key, value]);
}
return new Response(this.#socket._webResBody, {
status: this.statusCode,
statusText: this.statusMessage,
headers
});
}
};
async function fetchNodeHandler(handler, req) {
const nodeRuntime = req.runtime?.node;
if (nodeRuntime && nodeRuntime.req && nodeRuntime.res) return await callNodeHandler(handler, req);
const socket = new WebRequestSocket(req);
const nodeReq = new WebIncomingMessage(req, socket);
const nodeRes = new WebServerResponse(nodeReq, socket);
try {
await handler(nodeReq, nodeRes);
return await nodeRes.toWebResponse();
} catch (error) {
console.error(error, { cause: {
req,
handler
} });
return new Response(null, {
status: 500,
statusText: "Internal Server Error"
});
}
}
function toNodeHandler(handler) {
if (handler.__nodeHandler) return handler.__nodeHandler;
function convertedNodeHandler(nodeReq, nodeRes) {
const res = handler(new NodeRequest({
req: nodeReq,
res: nodeRes
}));
return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
}
convertedNodeHandler.__fetchHandler = handler;
assignFnName(convertedNodeHandler, handler, " (converted to Node handler)");
return convertedNodeHandler;
}
function toFetchHandler(handler) {
if (handler.__fetchHandler) return handler.__fetchHandler;
function convertedNodeHandler(req) {
return fetchNodeHandler(handler, req);
}
convertedNodeHandler.__nodeHandler = handler;
assignFnName(convertedNodeHandler, handler, " (converted to Web handler)");
return convertedNodeHandler;
}
function assignFnName(target, source, suffix) {
if (source.name) try {
Object.defineProperty(target, "name", { value: `${source.name}${suffix}` });
} catch {}
}
function serve(options) {
return new NodeServer(options);
}
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);
const loader = globalThis.__srvxLoader__;
if (loader) {
loader(fetchHandler);
return;
}
gracefulShutdownPlugin(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";
if (this.options.node?.http2 ?? this.#isSecure) if (this.#isSecure) server = nodeHTTP2.createSecureServer({
allowHTTP1: true,
...this.serveOptions
}, handler);
else throw new Error("node.http2 option requires tls certificate!");
else if (this.#isSecure) server = nodeHTTPS.createServer(this.serveOptions, handler);
else server = nodeHTTP.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 && closeAll && "closeAllConnections" in server) server.closeAllConnections();
if (!server || !server.listening) return resolve();
server.close((error) => error ? reject(error) : resolve());
})]);
}
};
export { NodeResponse as FastResponse, NodeResponse, FastURL, NodeRequest, fetchNodeHandler, patchGlobalRequest, sendNodeResponse, serve, toFetchHandler, 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 "../types.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 };

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

@@ -0,0 +1,76 @@
import { r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
const FastURL = URL;
const FastResponse = Response;
const isBrowserWindow = typeof window !== "undefined" && typeof navigator !== "undefined";
const isServiceWorker = 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();
}
};
export { FastResponse, FastURL, serve };

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

@@ -0,0 +1,57 @@
import { LoadOptions } from "./loader.mjs";
import { Server } from "srvx";
//#region src/cli/types.d.ts
declare global {
var __srvx__: Server | undefined;
}
type MainOptions = CLIOptions & {
args?: string[];
meta?: {
name?: string;
version?: string;
description?: string;
};
usage?: {
command?: string;
docs?: string;
issues?: string;
};
};
/**
* CLI options for srvx command
*/
type CLIOptions = {
/** CLI mode: "serve" to start a server, "fetch" to make HTTP requests */mode?: "serve" | "fetch"; /** Show help message */
help?: boolean; /** Show server and runtime versions */
version?: boolean; /** Working directory for resolving entry file */
dir?: string; /** Server entry file to use */
entry?: string; /** Run in production mode (no watch, no debug) */
prod?: boolean; /** Serve static files from the specified directory (default: "public") */
static?: string; /** ES module to preload */
import?: string; /** Host to bind to (default: all interfaces) */
hostname?: string; /** (alias to hostname) */
host?: string; /** Port to listen on (default: "3000") */
port?: string; /** Enable TLS (HTTPS/HTTP2) */
tls?: boolean; /** TLS certificate file */
cert?: string; /** TLS private key file */
key?: string; /** URL or path to fetch */
url?: string; /** HTTP method (default: "GET", or "POST" if body is provided) */
method?: string; /** Request headers (format: "Name: Value", can be used multiple times) */
header?: string[]; /** Show request and response headers */
verbose?: boolean; /** Request body (use "@-" for stdin, "@file" for file) */
data?: string;
};
//#endregion
//#region src/cli/main.d.ts
declare function main(mainOpts: MainOptions): Promise<void>;
//#endregion
//#region src/cli/fetch.d.ts
declare function cliFetch(cliOpts: CLIOptions & LoadOptions & {
loader?: LoadOptions;
stdin?: typeof process.stdin;
stdout?: typeof process.stdout;
stderr?: typeof process.stderr;
}): Promise<Response>;
//#endregion
export { type CLIOptions, type MainOptions, cliFetch, main };

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

@@ -0,0 +1,421 @@
import { a as green, c as url, i as gray, l as yellow, n as bold, o as magenta, r as cyan, s as red } from "./_chunks/_utils.mjs";
import { loadServerEntry } from "./loader.mjs";
import { parseArgs } from "node:util";
import { fileURLToPath } from "node:url";
import { fork } from "node:child_process";
import { createReadStream, existsSync, statSync } from "node:fs";
import { dirname, relative, resolve } from "node:path";
import { Readable } from "node:stream";
const NO_ENTRY_ERROR = "No server entry or public directory found";
async function cliServe(cliOpts) {
try {
if (!process.env.NODE_ENV) process.env.NODE_ENV = cliOpts.prod ? "production" : "development";
const loaded = await loadServerEntry({
entry: cliOpts.entry,
dir: cliOpts.dir
});
const { serve: srvxServe } = loaded.nodeCompat ? await import("srvx/node") : await import("srvx");
const { serveStatic } = await import("srvx/static");
const { log } = await import("srvx/log");
const staticDir = resolve(cliOpts.dir || (loaded.url ? dirname(fileURLToPath(loaded.url)) : "."), cliOpts.static || "public");
cliOpts.static = existsSync(staticDir) ? staticDir : "";
if (loaded.notFound && !cliOpts.static) {
process.send?.({ error: "no-entry" });
throw new Error(NO_ENTRY_ERROR, { cause: cliOpts });
}
const serverOptions = {
...loaded.module?.default,
default: void 0,
...loaded.module
};
printInfo(cliOpts, loaded);
await (globalThis.__srvx__ = srvxServe({
...serverOptions,
gracefulShutdown: !!cliOpts.prod,
port: cliOpts.port ?? serverOptions.port,
hostname: cliOpts.hostname ?? cliOpts.host ?? serverOptions.hostname,
tls: cliOpts.tls ? {
cert: cliOpts.cert,
key: cliOpts.key
} : void 0,
error: (error) => {
console.error(error);
return renderError(cliOpts, error);
},
fetch: loaded.fetch || (() => renderError(cliOpts, loaded.notFound ? "Server Entry Not Found" : "No Fetch Handler Exported", 501)),
middleware: [
log(),
cliOpts.static ? serveStatic({ dir: cliOpts.static }) : void 0,
...serverOptions.middleware || []
].filter(Boolean)
})).ready();
} catch (error) {
console.error(error);
process.exit(1);
}
}
function renderError(cliOpts, error, status = 500, title = "Server Error") {
let html = `<!DOCTYPE html><html><head><title>${title}</title></head><body>`;
if (cliOpts.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(cliOpts, loaded) {
let entryInfo;
if (loaded.notFound) entryInfo = gray(`(create ${bold(`server.ts`)})`);
else entryInfo = loaded.fetch ? cyan("./" + relative(".", fileURLToPath(loaded.url))) : red(`No fetch handler exported from ${loaded.url}`);
console.log(gray(`${bold(gray("◆"))} Server handler: ${entryInfo}`));
let staticInfo;
if (cliOpts.static) staticInfo = cyan("./" + relative(".", cliOpts.static) + "/");
else staticInfo = gray(`(create ${bold("public/")} dir)`);
console.log(gray(`${bold(gray("◇"))} Static files: ${staticInfo}`));
console.log("");
}
async function cliFetch(cliOpts) {
const stdin = cliOpts.stdin || process.stdin;
const stdout = cliOpts.stdout || process.stdout;
const stderr = cliOpts.stderr || process.stderr;
let fetchHandler = globalThis.fetch;
let inputURL = cliOpts.url || "/";
if (inputURL[0] === "/") {
const loaded = await loadServerEntry({
dir: cliOpts.dir,
entry: cliOpts.entry,
...cliOpts?.loader
});
if (cliOpts.verbose && loaded.url) {
stderr.write(`* Entry: ${fileURLToPath(loaded.url)}\n`);
if (loaded.nodeCompat) stderr.write(`* Using node compat mode\n`);
}
if (loaded.notFound) throw new Error(`Server entry file not found in ${resolve(cliOpts.dir || ".")}`, { cause: {
dir: cliOpts.dir || process.cwd(),
entry: cliOpts.entry || void 0
} });
else if (!loaded.fetch) throw new Error("No fetch handler exported", { cause: {
dir: cliOpts.dir || process.cwd(),
entry: cliOpts.entry || void 0,
loaded
} });
fetchHandler = loaded.fetch;
} else {
stderr.write(`* Fetching remote URL: ${inputURL}\n`);
if (!URL?.canParse(inputURL)) inputURL = `http${cliOpts.tls ? "s" : ""}://${inputURL}`;
fetchHandler = globalThis.fetch;
}
const headers = new Headers();
if (cliOpts.header) for (const header of cliOpts.header) {
const colonIndex = header.indexOf(":");
if (colonIndex > 0) {
const name = header.slice(0, colonIndex).trim();
const value = header.slice(colonIndex + 1).trim();
headers.append(name, value);
}
}
if (!headers.has("User-Agent")) headers.set("User-Agent", "srvx (curl)");
if (!headers.has("Accept")) headers.set("Accept", "text/markdown, application/json;q=0.9, text/plain;q=0.8, text/html;q=0.7, text/*;q=0.6, */*;q=0.5");
let body;
if (cliOpts.data !== void 0) if (cliOpts.data === "@-") body = new ReadableStream({ async start(controller) {
for await (const chunk of stdin) controller.enqueue(chunk);
controller.close();
} });
else if (cliOpts.data.startsWith("@")) body = Readable.toWeb(createReadStream(cliOpts.data.slice(1)));
else body = cliOpts.data;
const method = cliOpts.method || (body === void 0 ? "GET" : "POST");
const url = new URL(inputURL, `http${cliOpts.tls ? "s" : ""}://${cliOpts.host || cliOpts.hostname || "localhost"}`);
const req = new Request(url, {
method,
headers,
body
});
if (cliOpts.verbose) {
const parsedUrl = new URL(url);
stderr.write(`> ${method} ${parsedUrl.pathname}${parsedUrl.search} HTTP/1.1\n`);
stderr.write(`> Host: ${parsedUrl.host}\n`);
for (const [name, value] of headers) stderr.write(`> ${name}: ${value}\n`);
stderr.write(">\n");
}
const res = await fetchHandler(req);
if (cliOpts.verbose) {
stderr.write(`< HTTP/1.1 ${res.status} ${res.statusText}\n`);
for (const [name, value] of res.headers) stderr.write(`< ${name}: ${value}\n`);
stderr.write("<\n");
}
if (res.body) {
const { isBinary, encoding } = getResponseFormat(res);
if (isBinary) for await (const chunk of res.body) stdout.write(chunk);
else {
const decoder = new TextDecoder(encoding);
for await (const chunk of res.body) stdout.write(decoder.decode(chunk, { stream: true }));
const remaining = decoder.decode();
if (remaining) stdout.write(remaining);
if (stdout.isTTY) stdout.write("\n");
}
}
return res;
}
function getResponseFormat(res) {
const contentType = res.headers.get("content-type") || "";
return {
isBinary: contentType.startsWith("application/octet-stream") || contentType.startsWith("image/") || contentType.startsWith("audio/") || contentType.startsWith("video/") || contentType.startsWith("application/pdf") || contentType.startsWith("application/zip") || contentType.startsWith("application/gzip"),
encoding: contentType.includes("charset=") ? contentType.split("charset=")[1].split(";")[0].trim() : "utf8"
};
}
const srvxMeta = {
name: "srvx",
version: "0.11.3",
description: "Universal Server."
};
function usage(mainOpts) {
const command = mainOpts.usage?.command || "srvx";
const name = mainOpts.meta?.name || srvxMeta.name;
const ver = mainOpts.meta?.version || srvxMeta.version;
const desc = mainOpts.meta?.description || srvxMeta.description;
return `
${cyan(name)}${gray(`${ver ? ` ${ver}` : ""} ${desc ? `- ${desc}` : ""}`)}
${bold("SERVE MODE")}
${bold(green(`# ${command} serve [options]`))}
${gray("$")} ${cyan(command)} serve --entry ${gray("./server.ts")} ${gray("# Start development server")}
${gray("$")} ${cyan(command)} serve --prod ${gray("# Start production server")}
${gray("$")} ${cyan(command)} serve --port=8080 ${gray("# Listen on port 8080")}
${gray("$")} ${cyan(command)} serve --host=localhost ${gray("# Bind to localhost only")}
${gray("$")} ${cyan(command)} serve --import=jiti/register ${gray(`# Enable ${url("jiti", "https://github.com/unjs/jiti")} loader`)}
${gray("$")} ${cyan(command)} serve --tls --cert=cert.pem --key=key.pem ${gray("# Enable TLS (HTTPS/HTTP2)")}
${bold("FETCH MODE")}
${bold(green(`# ${command} fetch|curl [options] [url]`))}
${gray("$")} ${cyan(command)} fetch ${gray("# Fetch from default entry")}
${gray("$")} ${cyan(command)} fetch /api/users ${gray("# Fetch a specific URL/path")}
${gray("$")} ${cyan(command)} fetch --entry ./server.ts /api/users ${gray("# Fetch using a specific entry")}
${gray("$")} ${cyan(command)} fetch -X POST /api/users ${gray("# POST request")}
${gray("$")} ${cyan(command)} fetch -H "Content-Type: application/json" /api ${gray("# With headers")}
${gray("$")} ${cyan(command)} fetch -d '{"name":"foo"}' /api ${gray("# With request body")}
${gray("$")} ${cyan(command)} fetch -v /api/users ${gray("# Verbose output (show headers)")}
${gray("$")} echo '{"name":"foo"}' | ${cyan(command)} fetch -d @- /api ${gray("# Body from stdin")}
${bold("COMMON OPTIONS")}
${green("--entry")} ${yellow("<file>")} Server entry file to use
${green("--dir")} ${yellow("<dir>")} Working directory for resolving entry file
${green("-h, --help")} Show this help message
${green("--version")} Show server and runtime versions
${bold("SERVE OPTIONS")}
${green("-p, --port")} ${yellow("<port>")} Port to listen on (default: ${yellow("3000")})
${green("--host")} ${yellow("<host>")} Host to bind to (default: all interfaces)
${green("-s, --static")} ${yellow("<dir>")} Serve static files from the specified directory (default: ${yellow("public")})
${green("--prod")} Run in production mode (no watch, no debug)
${green("--import")} ${yellow("<loader>")} ES module to preload
${green("--tls")} Enable TLS (HTTPS/HTTP2)
${green("--cert")} ${yellow("<file>")} TLS certificate file
${green("--key")} ${yellow("<file>")} TLS private key file
${bold("FETCH OPTIONS")}
${green("-X, --request")} ${yellow("<method>")} HTTP method (default: ${yellow("GET")}, or ${yellow("POST")} if body is provided)
${green("-H, --header")} ${yellow("<header>")} Add header (format: "Name: Value", can be used multiple times)
${green("-d, --data")} ${yellow("<data>")} Request body (use ${yellow("@-")} for stdin, ${yellow("@file")} for file)
${green("-v, --verbose")} Show request and response headers
${bold("ENVIRONMENT")}
${green("PORT")} Override port
${green("HOST")} Override host
${green("NODE_ENV")} Set to ${yellow("production")} for production mode.
${mainOpts.usage?.docs ? `${url("Documentation", mainOpts.usage.docs)}` : ""}
${mainOpts.usage?.issues ? `${url("Report issues", mainOpts.usage.issues)}` : ""}
`.trim();
}
async function main(mainOpts) {
const args = process.argv.slice(2);
const cliOpts = parseArgs$1(args);
if (cliOpts.version) {
process.stdout.write(versions(mainOpts).join("\n") + "\n");
process.exit(0);
}
if (cliOpts.help) {
console.log(usage(mainOpts));
process.exit(cliOpts.help ? 0 : 1);
}
if (cliOpts.mode === "fetch") try {
const res = await cliFetch(cliOpts);
process.exit(res.ok ? 0 : 22);
} catch (error) {
console.error(error);
process.exit(1);
}
if (process.send) return startServer(cliOpts);
console.log(gray([...versions(mainOpts), cliOpts.prod ? "prod" : "dev"].join(" · ")));
const envFiles = [".env", cliOpts.prod ? ".env.production" : ".env.local"].filter((f) => existsSync(f));
if (envFiles.length > 0) console.log(`${gray(`Loading environment variables from ${magenta(envFiles.join(", "))}`)}`);
if (cliOpts.prod && !cliOpts.import) {
for (const envFile of [...envFiles].reverse()) process.loadEnvFile?.(envFile);
await startServer(cliOpts);
return;
}
const isBun = !!process.versions.bun;
const isDeno = !!process.versions.deno;
const isNode = !isBun && !isDeno;
const runtimeArgs = [];
runtimeArgs.push(...envFiles.map((f) => `--env-file=${f}`));
if (!cliOpts.prod) runtimeArgs.push("--watch");
if (cliOpts.import && (isNode || isBun)) runtimeArgs.push(`--import=${cliOpts.import}`);
await forkCLI(args, runtimeArgs);
}
function parseArgs$1(args) {
const pArg0 = args.find((a) => !a.startsWith("-"));
const mode = pArg0 === "fetch" || pArg0 === "curl" ? "fetch" : "serve";
const commonArgs = {
help: { type: "boolean" },
version: { type: "boolean" },
dir: { type: "string" },
entry: { type: "string" },
host: { type: "string" },
hostname: { type: "string" },
tls: { type: "boolean" }
};
if (mode === "serve") {
const { values, positionals } = parseArgs({
args,
allowPositionals: true,
options: {
...commonArgs,
url: { type: "string" },
prod: { type: "boolean" },
port: {
type: "string",
short: "p"
},
static: {
type: "string",
short: "s"
},
import: { type: "string" },
cert: { type: "string" },
key: { type: "string" }
}
});
if (positionals[0] === "serve") positionals.shift();
const maybeEntryOrDir = positionals[0];
if (maybeEntryOrDir) {
if (values.entry || values.dir) throw new Error("Cannot specify entry or dir as positional argument when --entry or --dir is used!");
if (statSync(maybeEntryOrDir).isDirectory()) values.dir = maybeEntryOrDir;
else values.entry = maybeEntryOrDir;
}
return {
mode,
...values
};
}
const { values, positionals } = parseArgs({
args,
allowPositionals: true,
options: {
...commonArgs,
url: { type: "string" },
method: {
type: "string",
short: "X"
},
request: { type: "string" },
header: {
type: "string",
multiple: true,
short: "H"
},
verbose: {
type: "boolean",
short: "v"
},
data: {
type: "string",
short: "d"
}
}
});
if (positionals[0] === "fetch" || positionals[0] === "curl") positionals.shift();
const method = values.method || values.request;
const url = values.url || positionals[0] || "/";
return {
mode,
...values,
url,
method
};
}
async function startServer(cliOpts) {
setupProcessErrorHandlers();
await cliServe(cliOpts);
}
async function forkCLI(args, runtimeArgs) {
const child = fork(fileURLToPath(globalThis.__SRVX_BIN__ || new URL("../bin/srvx.mjs", 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);
}
});
child.on("message", (msg) => {
if (msg && msg.error === "no-entry") {
console.error("\n" + red(NO_ENTRY_ERROR) + "\n");
process.exit(3);
}
});
let cleanupCalled = false;
const cleanup = (signal, exitCode) => {
if (cleanupCalled) return;
cleanupCalled = true;
try {
child.kill(signal || "SIGTERM");
} catch (error) {
console.error("Error killing child process:", error);
}
if (exitCode !== void 0) process.exit(exitCode);
};
process.on("exit", () => cleanup("SIGTERM"));
process.on("SIGTERM", () => cleanup("SIGTERM", 143));
if (args.includes("--watch")) process.on("SIGINT", () => cleanup("SIGINT", 130));
}
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);
});
}
function versions(mainOpts) {
const versions = [];
if (mainOpts.meta?.name) versions.push(`${mainOpts.meta.name} ${mainOpts.meta.version || ""}`.trim());
versions.push(`${srvxMeta.name} ${srvxMeta.version}`);
versions.push(runtime());
return versions;
}
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}`;
}
export { cliFetch, main };

74
node_modules/srvx/dist/loader.d.mts generated vendored Normal file
View File

@@ -0,0 +1,74 @@
import { ServerHandler } from "srvx";
//#region src/loader.d.ts
declare const defaultExts: string[];
declare const defaultEntries: string[];
/**
* Options for loading a server entry module.
*/
type LoadOptions = {
/**
* Path or URL to the server entry file.
*
* If not provided, common entry points will be searched automatically.
*/
entry?: string;
/**
* Base directory for resolving relative paths.
*
* @default "."
*/
dir?: string;
/**
* Set to `false` to disable interception of `http.Server.listen` to detect legacy handlers.
*
* @default true
*/
interceptHttpListen?: boolean;
/**
* Set to `false` to disable Node.js handler (req, res) compatibility.
*/
nodeCompat?: boolean;
/**
* Hook called after the module is loaded to allow for custom processing.
*
* You can return a modified version of the module if needed.
*/
onLoad?: (module: unknown) => any;
};
/**
* Result of loading a server entry module.
*/
type LoadedServerEntry = {
/**
* The web fetch handler extracted from the loaded module.
*
* This is resolved from `module.fetch`, `module.default.fetch`,
* or upgraded from a legacy Node.js handler.
*/
fetch?: ServerHandler;
/**
* The raw loaded module.
*/
module?: any;
/**
* Whether the handler was upgraded from a legacy Node.js HTTP handler.
*
* When `true`, the original module exported a Node.js-style `(req, res)` handler
* that has been wrapped for web fetch compatibility.
*/
nodeCompat?: boolean;
/**
* The resolved `file://` URL of the loaded entry module.
*/
url?: string;
/**
* Whether the specified entry file was not found.
*
* When `true`, no valid entry point could be located.
*/
notFound?: boolean;
};
declare function loadServerEntry(opts: LoadOptions): Promise<LoadedServerEntry>;
//#endregion
export { LoadOptions, LoadedServerEntry, defaultEntries, defaultExts, loadServerEntry };

116
node_modules/srvx/dist/loader.mjs generated vendored Normal file
View File

@@ -0,0 +1,116 @@
import { pathToFileURL } from "node:url";
import { existsSync } from "node:fs";
import { resolve } from "node:path";
import * as nodeHTTP$1 from "node:http";
const defaultExts = [
".mjs",
".js",
".mts",
".ts"
];
const defaultEntries = [
"server",
"server/index",
"src/server",
"server/server"
];
async function loadServerEntry(opts) {
let entry = opts.entry;
if (entry) {
entry = resolve(opts.dir || ".", entry);
if (!existsSync(entry)) return { notFound: true };
} else {
for (const defEntry of defaultEntries) {
for (const defExt of defaultExts) {
const entryPath = resolve(opts.dir || ".", `${defEntry}${defExt}`);
if (existsSync(entryPath)) {
entry = entryPath;
break;
}
}
if (entry) break;
}
if (!entry) return { notFound: true };
}
const url = entry.startsWith("file://") ? entry : pathToFileURL(resolve(entry)).href;
let mod;
let interceptedNodeHandler;
let interceptedFetchHandler;
try {
if (opts.interceptHttpListen !== false) {
const loaded = await interceptListen(() => import(url));
mod = loaded.res;
interceptedNodeHandler = loaded.listenHandler;
interceptedFetchHandler = loaded.fetchHandler;
} else mod = await import(url);
} catch (error) {
if (error?.code === "ERR_UNKNOWN_FILE_EXTENSION") {
const message = String(error);
if (/"\.(m|c)?ts"/g.test(message)) throw new Error(`Make sure you're using Node.js v22.18+ or v24+ for TypeScript support (current version: ${process.versions.node})`, { cause: error });
else if (/"\.(m|c)?tsx"/g.test(message)) throw new Error(`You need a compatible loader for JSX support (Deno, Bun or srvx --register jiti/register)`, { cause: error });
}
throw error;
}
mod = await opts?.onLoad?.(mod) || mod;
let fetchHandler = mod?.fetch || mod?.default?.fetch || mod?.default?.default?.fetch || interceptedFetchHandler;
if (!fetchHandler && typeof mod?.default === "function" && mod.default.length < 2) fetchHandler = mod.default;
let nodeCompat = false;
if (!fetchHandler && opts.nodeCompat !== false) {
const nodeHandler = interceptedNodeHandler || (typeof mod?.default === "function" ? mod.default : void 0);
if (nodeHandler) {
nodeCompat = true;
const { fetchNodeHandler } = await import("srvx/node");
fetchHandler = (webReq) => fetchNodeHandler(nodeHandler, webReq);
}
}
return {
module: mod,
nodeCompat,
url,
fetch: fetchHandler
};
}
let _interceptQueue = Promise.resolve();
async function interceptListen(cb) {
const result = _interceptQueue.then(async () => {
const originalListen = nodeHTTP$1.Server.prototype.listen;
let res;
let listenHandler;
let fetchHandler;
globalThis.__srvxLoader__ = (handler) => {
fetchHandler = handler;
};
try {
nodeHTTP$1.Server.prototype.listen = function(arg1, arg2) {
listenHandler = this._events.request;
if (Array.isArray(listenHandler)) listenHandler = listenHandler[0];
nodeHTTP$1.Server.prototype.listen = originalListen;
const listenCallback = [arg1, arg2].find((arg) => typeof arg === "function");
setImmediate(() => {
listenCallback?.();
});
return new Proxy({}, { get(_, prop) {
const server = globalThis.__srvx__;
if (!server && prop === "address") return () => ({
address: "",
family: "",
port: 0
});
return server?.node?.server?.[prop];
} });
};
res = await cb();
} finally {
nodeHTTP$1.Server.prototype.listen = originalListen;
delete globalThis.__srvxLoader__;
}
return {
res,
listenHandler,
fetchHandler
};
});
_interceptQueue = result.catch(() => {});
return result;
}
export { defaultEntries, defaultExts, loadServerEntry };

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

@@ -0,0 +1,7 @@
import { ServerMiddleware } from "./types.mjs";
//#region src/log.d.ts
interface LogOptions {}
declare const log: (_options?: LogOptions) => ServerMiddleware;
//#endregion
export { LogOptions, log };

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

@@ -0,0 +1,17 @@
import { a as green, i as gray, l as yellow, n as bold, s as red, t as blue } from "./_chunks/_utils.mjs";
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(`${gray(`[${(/* @__PURE__ */ new Date()).toLocaleTimeString()}]`)} ${bold(req.method)} ${blue(req.url)} [${statusColor(res.status + "")}] ${gray(`(${duration.toFixed(2)}ms)`)}`);
return res;
};
};
export { log };

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

@@ -0,0 +1,24 @@
import { ServerMiddleware } from "./types.mjs";
//#region src/static.d.ts
interface ServeStaticOptions {
/**
* The directory to serve static files from.
*/
dir: string;
/**
* The HTTP methods to allow for serving static files.
*/
methods?: string[];
/**
* A function to modify the HTML content before serving it.
*/
renderHTML?: (ctx: {
request: Request;
html: string;
filename: string;
}) => Response | Promise<Response>;
}
declare const serveStatic: (options: ServeStaticOptions) => ServerMiddleware;
//#endregion
export { ServeStaticOptions, serveStatic };

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

@@ -0,0 +1,74 @@
import { t as FastURL } from "./_chunks/_url.mjs";
import { createReadStream } from "node:fs";
import { extname, join, resolve } from "node:path";
import { readFile, stat } from "node:fs/promises";
import { FastResponse } from "srvx";
import { createBrotliCompress, createGzip } from "node:zlib";
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) + "/";
const methods = new Set((options.methods || ["GET", "HEAD"]).map((m) => m.toUpperCase()));
return async (req, next) => {
if (!methods.has(req.method)) return next();
const path = (req._url ??= new FastURL(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 of paths) {
const filePath = join(dir, path);
if (!filePath.startsWith(dir)) continue;
const fileStat = await stat(filePath).catch(() => null);
if (fileStat?.isFile()) {
const fileExt = extname(filePath);
const headers = {
"Content-Length": fileStat.size.toString(),
"Content-Type": COMMON_MIME_TYPES[fileExt] || "application/octet-stream"
};
if (options.renderHTML && fileExt === ".html") return options.renderHTML({
html: await readFile(filePath, "utf8"),
filename: filePath,
request: req
});
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();
};
};
export { serveStatic };

41
node_modules/srvx/dist/tracing.d.mts generated vendored Normal file
View File

@@ -0,0 +1,41 @@
import { Server, ServerMiddleware, ServerPlugin, ServerRequest } from "./types.mjs";
//#region src/tracing.d.ts
/**
* @experimental Channel names, event types and config options may change in future releases.
*/
type RequestEvent = {
server: Server;
request: ServerRequest;
middleware?: {
index: number;
handler: ServerMiddleware;
};
};
/**
*
* @experimental Channel names, event types and config options may change in future releases.
*
* Tracing plugin that adds diagnostics channel tracing to middleware and fetch handlers.
*
* This plugin wraps all middleware and the fetch handler with tracing instrumentation,
* allowing you to subscribe to `srvx.request` and `srvx.middleware` tracing channels.
*
* @example
* ```ts
* import { serve } from "srvx";
* import { tracingPlugin } from "srvx/tracing";
*
* const server = serve({
* fetch: (req) => new Response("OK"),
* middleware: [myMiddleware],
* plugins: [tracingPlugin()],
* });
* ```
*/
declare function tracingPlugin(opts?: {
middleware?: boolean;
fetch?: boolean;
}): ServerPlugin;
//#endregion
export { RequestEvent, tracingPlugin };

34
node_modules/srvx/dist/tracing.mjs generated vendored Normal file
View File

@@ -0,0 +1,34 @@
function tracingPlugin(opts = {}) {
return (server) => {
const { tracingChannel } = globalThis.process?.getBuiltinModule?.("node:diagnostics_channel") || {};
if (!tracingChannel) return;
if (opts.fetch !== false) {
const fetchChannel = tracingChannel("srvx.request");
const originalFetch = server.options.fetch;
server.options.fetch = (request) => {
return fetchChannel.tracePromise(async () => await originalFetch(request), {
request,
server
});
};
}
if (opts.middleware !== false) {
const middlewareChannel = tracingChannel("srvx.middleware");
const wrappedMiddleware = server.options.middleware.map((handler, index) => {
const middleware = Object.freeze({
index,
handler
});
return (request, next) => {
return middlewareChannel.tracePromise(async () => await handler(request, next), {
request,
server,
middleware
});
};
});
server.options.middleware.splice(0, server.options.middleware.length, ...wrappedMiddleware);
}
};
}
export { tracingPlugin };

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

@@ -0,0 +1,303 @@
import * as NodeHttp from "node:http";
import * as NodeHttps from "node:https";
import * as NodeHttp2 from "node:http2";
import * as AWS from "aws-lambda";
import * as cloudflare_workers0 from "cloudflare:workers";
import * as NodeNet from "node:net";
import * as Bun from "bun";
import * as CF from "@cloudflare/workers-types";
//#region src/types.d.ts
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;
/**
* 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;
/**
* Graceful shutdown on SIGINT and SIGTERM signals.
*
* Supported for Node.js, Deno and Bun runtimes.
*
* @default true (disabled in test and ci environments)
*/
gracefulShutdown?: boolean | {
gracefulTimeout?: number;
forceTimeout?: number;
};
/**
* 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.ServerOptions | NodeHttps.ServerOptions | NodeHttp2.ServerOptions) & NodeNet.ListenOptions & {
http2?: boolean;
};
/**
* Bun server options
*
* @docs https://bun.sh/docs/api/http
*/
bun?: Omit<Bun.Serve.Options<any>, "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" | "aws-lambda" | "generic";
/**
* Server options
*/
readonly options: ServerOptions & {
middleware: ServerMiddleware[];
};
/**
* Server URL address.
*/
readonly url?: string;
/**
* Node.js context.
*/
readonly node?: {
server?: NodeHttp.Server | NodeHttp2.Http2Server;
handler: (req: NodeServerRequest, res: NodeServerResponse) => void | Promise<void>;
};
/**
* Bun context.
*/
readonly bun?: {
server?: Bun.Server<any>;
};
/**
* 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>;
}
interface ServerRuntimeContext {
name: "node" | "deno" | "bun" | "cloudflare" | "aws-lambda" | (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<any>;
};
/**
* Underlying Cloudflare request context.
*/
cloudflare?: {
context: CF.ExecutionContext;
env: IsAny<typeof cloudflare_workers0> extends true ? Record<string, unknown> : typeof cloudflare_workers0.env;
};
awsLambda?: {
context: AWS.Context;
event: AWS.APIGatewayProxyEvent | AWS.APIGatewayProxyEventV2;
};
serviceWorker?: {
event: FetchEvent;
};
netlify?: {
context: any;
};
stormkit?: {
event: any;
context: any;
};
vercel?: {
context: {
waitUntil?: (promise: Promise<any>) => void;
};
};
}
interface ServerRequestContext {
[key: string]: unknown;
}
interface ServerRequest extends Request {
/**
* Access to Node.js native instance of request.
*
* See https://srvx.h3.dev/guide/node#noderequest
*/
_request?: Request;
/**
* Access to the parsed URL
*/
_url?: URL;
/**
* 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>;
}
type FetchHandler = (request: Request) => Response | Promise<Response>;
type ErrorHandler = (error: unknown) => Response | Promise<Response>;
type BunFetchHandler = (request: Request, server?: Bun.Server<any>) => Response | Promise<Response>;
type DenoFetchHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.NetAddr>) => Response | Promise<Response>;
type NodeServerRequest = NodeHttp.IncomingMessage | NodeHttp2.Http2ServerRequest;
type NodeServerResponse = NodeHttp.ServerResponse | NodeHttp2.Http2ServerResponse;
type NodeHttp1Handler = (req: NodeHttp.IncomingMessage, res: NodeHttp.ServerResponse) => void | Promise<void>;
type NodeHttp2Handler = (req: NodeHttp2.Http2ServerRequest, res: NodeHttp2.Http2ServerResponse) => void | Promise<void>;
type NodeHttpHandler = NodeHttp1Handler | NodeHttp2Handler;
type NodeHTTP1Middleware = (req: NodeHttp.IncomingMessage, res: NodeHttp.ServerResponse, next: (error?: Error) => void) => unknown | Promise<unknown>;
type NodeHTTP2Middleware = (req: NodeHttp2.Http2ServerRequest, res: NodeHttp2.Http2ServerResponse, next: (error?: Error) => void) => unknown | Promise<unknown>;
type NodeHTTPMiddleware = NodeHTTP1Middleware | NodeHTTP2Middleware;
type CloudflareFetchHandler = CF.ExportedHandlerFetchHandler;
//#endregion
export { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTP1Middleware, NodeHTTP2Middleware, NodeHTTPMiddleware, NodeHttp1Handler, NodeHttp2Handler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, serve };

101
node_modules/srvx/package.json generated vendored Normal file
View File

@@ -0,0 +1,101 @@
{
"name": "srvx",
"version": "0.11.4",
"description": "Universal Server.",
"homepage": "https://srvx.h3.dev",
"license": "MIT",
"repository": "h3js/srvx",
"bin": {
"srvx": "./bin/srvx.mjs"
},
"files": [
"bin",
"dist"
],
"type": "module",
"sideEffects": false,
"types": "./dist/types.d.mts",
"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",
"./aws-lambda": "./dist/adapters/aws-lambda.mjs",
"./cli": "./dist/cli.mjs",
"./static": "./dist/static.mjs",
"./log": "./dist/log.mjs",
"./tracing": "./dist/tracing.mjs",
"./loader": "./dist/loader.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"
}
},
"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 node ./test/url.bench.ts",
"build": "obuild",
"dev": "vitest dev",
"lint": "oxlint . && oxfmt --check .",
"lint:fix": "automd && oxlint . --fix && oxfmt .",
"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 && pnpm build && changelogen --release && npm publish && git push --follow-tags",
"srvx": "./bin/srvx.mjs",
"test": "pnpm lint && pnpm typecheck && vitest run --coverage",
"test:node-compat:deno": "deno run vitest test/node.test",
"test:node-compat:bun": "bun vitest test/node.test.ts",
"typecheck": "tsgo --noEmit --skipLibCheck",
"vitest": "vitest"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20260210.0",
"@hono/node-server": "^1.19.9",
"@mitata/counters": "^0.0.8",
"@mjackson/node-fetch-server": "^0.7.0",
"@types/aws-lambda": "^8.10.160",
"@types/bun": "^1.3.8",
"@types/deno": "^2.5.0",
"@types/express": "^5.0.6",
"@types/node": "^25.2.3",
"@types/node-forge": "^1.3.14",
"@types/serviceworker": "^0.0.186",
"@typescript/native-preview": "^7.0.0-dev.20260210.1",
"@vitest/coverage-v8": "^4.0.18",
"@whatwg-node/server": "^0.10.18",
"automd": "^0.4.3",
"changelogen": "^0.6.2",
"eslint-config-unjs": "^0.6.2",
"execa": "^9.6.1",
"express": "^5.2.1",
"fastify": "^5.7.4",
"get-port-please": "^3.2.0",
"mdbox": "^0.1.1",
"mitata": "^1.0.34",
"node-forge": "^1.3.3",
"obuild": "^0.4.27",
"oxfmt": "^0.28.0",
"oxlint": "^1.43.0",
"srvx-release": "npm:srvx@^0.10.1",
"tslib": "^2.8.1",
"typescript": "^5.9.3",
"undici": "^7.21.0",
"vitest": "^4.0.18"
},
"resolutions": {
"srvx": "link:."
},
"engines": {
"node": ">=20.16.0"
},
"packageManager": "pnpm@10.29.2"
}