Update app and tooling
This commit is contained in:
parent
3046531bdd
commit
e620ec7349
4950 changed files with 2975120 additions and 10 deletions
13
node_modules/srvx/dist/_chunks/_middleware-BvRR7B4M.mjs
generated
vendored
Normal file
13
node_modules/srvx/dist/_chunks/_middleware-BvRR7B4M.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
//#region src/_middleware.ts
|
||||
function wrapFetch(server) {
|
||||
const fetchHandler = server.options.fetch;
|
||||
const middleware = server.options.middleware || [];
|
||||
return middleware.length === 0 ? fetchHandler : (request) => callMiddleware(request, fetchHandler, middleware, 0);
|
||||
}
|
||||
function callMiddleware(request, fetchHandler, middleware, index) {
|
||||
if (index === middleware.length) return fetchHandler(request);
|
||||
return middleware[index](request, () => callMiddleware(request, fetchHandler, middleware, index + 1));
|
||||
}
|
||||
|
||||
//#endregion
|
||||
export { wrapFetch };
|
||||
16
node_modules/srvx/dist/_chunks/_plugins-DOhVIkXu.mjs
generated
vendored
Normal file
16
node_modules/srvx/dist/_chunks/_plugins-DOhVIkXu.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//#region src/_plugins.ts
|
||||
const errorPlugin = (server) => {
|
||||
const errorHandler = server.options.error;
|
||||
if (!errorHandler) return;
|
||||
server.options.middleware.unshift((_req, next) => {
|
||||
try {
|
||||
const res = next();
|
||||
return res instanceof Promise ? res.catch((error) => errorHandler(error)) : res;
|
||||
} catch (error) {
|
||||
return errorHandler(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { errorPlugin };
|
||||
91
node_modules/srvx/dist/_chunks/_url-CdE4ce6F.mjs
generated
vendored
Normal file
91
node_modules/srvx/dist/_chunks/_url-CdE4ce6F.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
//#region src/_url.ts
|
||||
/**
|
||||
* Wrapper for URL with fast path access to `.pathname` and `.search` props.
|
||||
*
|
||||
* **NOTE:** It is assumed that the input URL is already ecoded and formatted from an HTTP request and contains no hash.
|
||||
*
|
||||
* **NOTE:** Triggering the setters or getters on other props will deoptimize to full URL parsing.
|
||||
*/
|
||||
const FastURL = /* @__PURE__ */ (() => {
|
||||
const FastURL$1 = class URL {
|
||||
#originalURL;
|
||||
#parsedURL;
|
||||
_pathname;
|
||||
_urlqindex;
|
||||
_query;
|
||||
_search;
|
||||
constructor(url) {
|
||||
this.#originalURL = url;
|
||||
}
|
||||
get _url() {
|
||||
if (!this.#parsedURL) this.#parsedURL = new globalThis.URL(this.#originalURL);
|
||||
return this.#parsedURL;
|
||||
}
|
||||
toString() {
|
||||
return this._url.toString();
|
||||
}
|
||||
toJSON() {
|
||||
return this.toString();
|
||||
}
|
||||
get pathname() {
|
||||
if (this.#parsedURL) return this.#parsedURL.pathname;
|
||||
if (this._pathname === void 0) {
|
||||
const url = this.#originalURL;
|
||||
const protoIndex = url.indexOf("://");
|
||||
if (protoIndex === -1) return this._url.pathname;
|
||||
const pIndex = url.indexOf("/", protoIndex + 4);
|
||||
if (pIndex === -1) return this._url.pathname;
|
||||
const qIndex = this._urlqindex = url.indexOf("?", pIndex);
|
||||
this._pathname = url.slice(pIndex, qIndex === -1 ? void 0 : qIndex);
|
||||
}
|
||||
return this._pathname;
|
||||
}
|
||||
set pathname(value) {
|
||||
this._pathname = void 0;
|
||||
this._url.pathname = value;
|
||||
}
|
||||
get searchParams() {
|
||||
if (this.#parsedURL) return this.#parsedURL.searchParams;
|
||||
if (!this._query) this._query = new URLSearchParams(this.search);
|
||||
return this._query;
|
||||
}
|
||||
get search() {
|
||||
if (this.#parsedURL) return this.#parsedURL.search;
|
||||
if (this._search === void 0) {
|
||||
const qIndex = this._urlqindex;
|
||||
if (qIndex === -1 || qIndex === this.#originalURL.length - 1) this._search = "";
|
||||
else this._search = qIndex === void 0 ? this._url.search : this.#originalURL.slice(qIndex);
|
||||
}
|
||||
return this._search;
|
||||
}
|
||||
set search(value) {
|
||||
this._search = void 0;
|
||||
this._query = void 0;
|
||||
this._url.search = value;
|
||||
}
|
||||
};
|
||||
const slowProps = [
|
||||
"hash",
|
||||
"host",
|
||||
"hostname",
|
||||
"href",
|
||||
"origin",
|
||||
"password",
|
||||
"port",
|
||||
"protocol",
|
||||
"username"
|
||||
];
|
||||
for (const prop of slowProps) Object.defineProperty(FastURL$1.prototype, prop, {
|
||||
get() {
|
||||
return this._url[prop];
|
||||
},
|
||||
set(value) {
|
||||
this._url[prop] = value;
|
||||
}
|
||||
});
|
||||
Object.setPrototypeOf(FastURL$1, globalThis.URL);
|
||||
return FastURL$1;
|
||||
})();
|
||||
|
||||
//#endregion
|
||||
export { FastURL as FastURL$1 };
|
||||
13
node_modules/srvx/dist/_chunks/_url-D8u5OAto.d.mts
generated
vendored
Normal file
13
node_modules/srvx/dist/_chunks/_url-D8u5OAto.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
//#region src/_url.d.ts
|
||||
/**
|
||||
* Wrapper for URL with fast path access to `.pathname` and `.search` props.
|
||||
*
|
||||
* **NOTE:** It is assumed that the input URL is already ecoded and formatted from an HTTP request and contains no hash.
|
||||
*
|
||||
* **NOTE:** Triggering the setters or getters on other props will deoptimize to full URL parsing.
|
||||
*/
|
||||
declare const FastURL: {
|
||||
new (url: string): URL;
|
||||
};
|
||||
//#endregion
|
||||
export { FastURL as FastURL$2 };
|
||||
70
node_modules/srvx/dist/_chunks/_utils-DRF_4b_y.mjs
generated
vendored
Normal file
70
node_modules/srvx/dist/_chunks/_utils-DRF_4b_y.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//#region src/_utils.ts
|
||||
function resolvePortAndHost(opts) {
|
||||
const _port = opts.port ?? globalThis.process?.env.PORT ?? 3e3;
|
||||
const port = typeof _port === "number" ? _port : Number.parseInt(_port, 10);
|
||||
const hostname = opts.hostname ?? globalThis.process?.env.HOST;
|
||||
return {
|
||||
port,
|
||||
hostname
|
||||
};
|
||||
}
|
||||
function fmtURL(host, port, secure) {
|
||||
if (!host || !port) return void 0;
|
||||
if (host.includes(":")) host = `[${host}]`;
|
||||
return `http${secure ? "s" : ""}://${host}:${port}/`;
|
||||
}
|
||||
function printListening(opts, url) {
|
||||
if (!url || (opts.silent ?? globalThis.process?.env?.TEST)) return;
|
||||
const _url = new URL(url);
|
||||
const allInterfaces = _url.hostname === "[::]" || _url.hostname === "0.0.0.0";
|
||||
if (allInterfaces) {
|
||||
_url.hostname = "localhost";
|
||||
url = _url.href;
|
||||
}
|
||||
let listeningOn = `➜ Listening on:`;
|
||||
let additionalInfo = allInterfaces ? " (all interfaces)" : "";
|
||||
if (globalThis.process.stdout?.isTTY) {
|
||||
listeningOn = `\u001B[32m${listeningOn}\u001B[0m`;
|
||||
url = `\u001B[36m${url}\u001B[0m`;
|
||||
additionalInfo = `\u001B[2m${additionalInfo}\u001B[0m`;
|
||||
}
|
||||
console.log(`${listeningOn} ${url}${additionalInfo}`);
|
||||
}
|
||||
function resolveTLSOptions(opts) {
|
||||
if (!opts.tls || opts.protocol === "http") return;
|
||||
const cert = resolveCertOrKey(opts.tls.cert);
|
||||
const key = resolveCertOrKey(opts.tls.key);
|
||||
if (!cert && !key) {
|
||||
if (opts.protocol === "https") throw new TypeError("TLS `cert` and `key` must be provided for `https` protocol.");
|
||||
return;
|
||||
}
|
||||
if (!cert || !key) throw new TypeError("TLS `cert` and `key` must be provided together.");
|
||||
return {
|
||||
cert,
|
||||
key,
|
||||
passphrase: opts.tls.passphrase
|
||||
};
|
||||
}
|
||||
function resolveCertOrKey(value) {
|
||||
if (!value) return;
|
||||
if (typeof value !== "string") throw new TypeError("TLS certificate and key must be strings in PEM format or file paths.");
|
||||
if (value.startsWith("-----BEGIN ")) return value;
|
||||
const { readFileSync } = process.getBuiltinModule("node:fs");
|
||||
return readFileSync(value, "utf8");
|
||||
}
|
||||
function createWaitUntil() {
|
||||
const promises = new Set();
|
||||
return {
|
||||
waitUntil: (promise) => {
|
||||
promises.add(promise.catch(console.error).finally(() => {
|
||||
promises.delete(promise);
|
||||
}));
|
||||
},
|
||||
wait: () => {
|
||||
return Promise.all(promises);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//#endregion
|
||||
export { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions };
|
||||
31
node_modules/srvx/dist/_chunks/_utils.cli-B2YzwlOv.mjs
generated
vendored
Normal file
31
node_modules/srvx/dist/_chunks/_utils.cli-B2YzwlOv.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
//#region src/_utils.cli.ts
|
||||
const noColor = globalThis.process?.env?.NO_COLOR === "1" || globalThis.process?.env?.TERM === "dumb";
|
||||
const resets = {
|
||||
1: 22,
|
||||
31: 39,
|
||||
32: 39,
|
||||
33: 39,
|
||||
34: 39,
|
||||
35: 39,
|
||||
36: 39,
|
||||
90: 39
|
||||
};
|
||||
const _c = (c) => (text) => {
|
||||
if (noColor) return text;
|
||||
const off = resets[c] ?? 0;
|
||||
return `\u001B[${c}m${text}\u001B[${off}m`;
|
||||
};
|
||||
const Colors = {
|
||||
bold: _c(1),
|
||||
red: _c(31),
|
||||
green: _c(32),
|
||||
yellow: _c(33),
|
||||
blue: _c(34),
|
||||
magenta: _c(35),
|
||||
cyan: _c(36),
|
||||
gray: _c(90),
|
||||
url: (title, url) => noColor ? `[${title}](${url})` : `\u001B]8;;${url}\u001B\\${title}\u001B]8;;\u001B\\`
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { Colors };
|
||||
43
node_modules/srvx/dist/_chunks/call-LB9MY5Dv.mjs
generated
vendored
Normal file
43
node_modules/srvx/dist/_chunks/call-LB9MY5Dv.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import { NodeResponse, NodeResponseHeaders } from "./response-6LJL3Qlz.mjs";
|
||||
|
||||
//#region src/adapters/_node/call.ts
|
||||
function callNodeHandler(handler, req) {
|
||||
const isMiddleware = handler.length > 2;
|
||||
const nodeCtx = req.runtime?.node;
|
||||
if (!nodeCtx || !nodeCtx.req || !nodeCtx.res) throw new Error("Node.js runtime context is not available.");
|
||||
const { req: nodeReq, res: nodeRes } = nodeCtx;
|
||||
let _headers;
|
||||
const webRes = new NodeResponse(void 0, {
|
||||
get status() {
|
||||
return nodeRes.statusCode;
|
||||
},
|
||||
get statusText() {
|
||||
return nodeRes.statusMessage;
|
||||
},
|
||||
get headers() {
|
||||
if (!_headers) _headers = new NodeResponseHeaders(nodeCtx);
|
||||
return _headers;
|
||||
}
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
nodeRes.once("close", () => resolve(webRes));
|
||||
nodeRes.once("finish", () => resolve(webRes));
|
||||
nodeRes.once("error", (error) => reject(error));
|
||||
let streamPromise;
|
||||
nodeRes.once("pipe", (stream) => {
|
||||
streamPromise = new Promise((resolve$1) => {
|
||||
stream.once("end", () => resolve$1(webRes));
|
||||
stream.once("error", (error) => reject(error));
|
||||
});
|
||||
});
|
||||
try {
|
||||
if (isMiddleware) Promise.resolve(handler(nodeReq, nodeRes, (error) => error ? reject(error) : streamPromise || resolve(webRes))).catch((error) => reject(error));
|
||||
else Promise.resolve(handler(nodeReq, nodeRes)).then(() => streamPromise || webRes);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//#endregion
|
||||
export { callNodeHandler };
|
||||
293
node_modules/srvx/dist/_chunks/response-6LJL3Qlz.mjs
generated
vendored
Normal file
293
node_modules/srvx/dist/_chunks/response-6LJL3Qlz.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
import { splitSetCookieString } from "cookie-es";
|
||||
|
||||
//#region src/adapters/_node/_common.ts
|
||||
const kNodeInspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
||||
function inheritProps(target, source, sourceKey) {
|
||||
for (const key of Object.getOwnPropertyNames(source)) {
|
||||
if (key in target) continue;
|
||||
const desc = Object.getOwnPropertyDescriptor(source, key);
|
||||
if (desc.get) Object.defineProperty(target, key, {
|
||||
...desc,
|
||||
get() {
|
||||
return this[sourceKey][key];
|
||||
}
|
||||
});
|
||||
else if (typeof desc.value === "function") Object.defineProperty(target, key, {
|
||||
...desc,
|
||||
value(...args) {
|
||||
return this[sourceKey][key](...args);
|
||||
}
|
||||
});
|
||||
else Object.defineProperty(target, key, desc);
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/adapters/_node/headers.ts
|
||||
const NodeRequestHeaders = /* @__PURE__ */ (() => {
|
||||
const _Headers = class Headers$1 {
|
||||
_node;
|
||||
constructor(nodeCtx) {
|
||||
this._node = nodeCtx;
|
||||
}
|
||||
append(name, value) {
|
||||
name = validateHeader(name);
|
||||
const _headers = this._node.req.headers;
|
||||
const _current = _headers[name];
|
||||
if (_current) if (Array.isArray(_current)) _current.push(value);
|
||||
else _headers[name] = [_current, value];
|
||||
else _headers[name] = value;
|
||||
}
|
||||
delete(name) {
|
||||
name = validateHeader(name);
|
||||
this._node.req.headers[name] = void 0;
|
||||
}
|
||||
get(name) {
|
||||
name = validateHeader(name);
|
||||
const rawValue = this._node.req.headers[name];
|
||||
if (rawValue === void 0) return null;
|
||||
return _normalizeValue(this._node.req.headers[name]);
|
||||
}
|
||||
getSetCookie() {
|
||||
const setCookie = this._node.req.headers["set-cookie"];
|
||||
if (!setCookie || setCookie.length === 0) return [];
|
||||
return splitSetCookieString(setCookie);
|
||||
}
|
||||
has(name) {
|
||||
name = validateHeader(name);
|
||||
return !!this._node.req.headers[name];
|
||||
}
|
||||
set(name, value) {
|
||||
name = validateHeader(name);
|
||||
this._node.req.headers[name] = value;
|
||||
}
|
||||
get count() {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getAll(_name) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
toJSON() {
|
||||
const _headers = this._node.req.headers;
|
||||
const result = {};
|
||||
for (const key in _headers) if (_headers[key]) result[key] = _normalizeValue(_headers[key]);
|
||||
return result;
|
||||
}
|
||||
forEach(cb, thisArg) {
|
||||
const _headers = this._node.req.headers;
|
||||
for (const key in _headers) if (_headers[key]) cb.call(thisArg, _normalizeValue(_headers[key]), key, this);
|
||||
}
|
||||
*entries() {
|
||||
const headers = this._node.req.headers;
|
||||
const isHttp2 = this._node.req.httpVersion === "2.0";
|
||||
for (const key in headers) if (!isHttp2 || key[0] !== ":") yield [key, _normalizeValue(headers[key])];
|
||||
}
|
||||
*keys() {
|
||||
const keys = Object.keys(this._node.req.headers);
|
||||
for (const key of keys) yield key;
|
||||
}
|
||||
*values() {
|
||||
const values = Object.values(this._node.req.headers);
|
||||
for (const value of values) yield _normalizeValue(value);
|
||||
}
|
||||
[Symbol.iterator]() {
|
||||
return this.entries()[Symbol.iterator]();
|
||||
}
|
||||
get [Symbol.toStringTag]() {
|
||||
return "Headers";
|
||||
}
|
||||
[kNodeInspect]() {
|
||||
return Object.fromEntries(this.entries());
|
||||
}
|
||||
};
|
||||
Object.setPrototypeOf(_Headers.prototype, globalThis.Headers.prototype);
|
||||
return _Headers;
|
||||
})();
|
||||
const NodeResponseHeaders = /* @__PURE__ */ (() => {
|
||||
const _Headers = class Headers$1 {
|
||||
_node;
|
||||
constructor(nodeCtx) {
|
||||
this._node = nodeCtx;
|
||||
}
|
||||
append(name, value) {
|
||||
this._node.res.appendHeader(name, value);
|
||||
}
|
||||
delete(name) {
|
||||
this._node.res.removeHeader(name);
|
||||
}
|
||||
get(name) {
|
||||
const rawValue = this._node.res.getHeader(name);
|
||||
if (rawValue === void 0) return null;
|
||||
return _normalizeValue(rawValue);
|
||||
}
|
||||
getSetCookie() {
|
||||
const setCookie = _normalizeValue(this._node.res.getHeader("set-cookie"));
|
||||
if (!setCookie) return [];
|
||||
return splitSetCookieString(setCookie);
|
||||
}
|
||||
has(name) {
|
||||
return this._node.res.hasHeader(name);
|
||||
}
|
||||
set(name, value) {
|
||||
this._node.res.setHeader(name, value);
|
||||
}
|
||||
get count() {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getAll(_name) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
toJSON() {
|
||||
const _headers = this._node.res.getHeaders();
|
||||
const result = {};
|
||||
for (const key in _headers) if (_headers[key]) result[key] = _normalizeValue(_headers[key]);
|
||||
return result;
|
||||
}
|
||||
forEach(cb, thisArg) {
|
||||
const _headers = this._node.res.getHeaders();
|
||||
for (const key in _headers) if (_headers[key]) cb.call(thisArg, _normalizeValue(_headers[key]), key, this);
|
||||
}
|
||||
*entries() {
|
||||
const _headers = this._node.res.getHeaders();
|
||||
for (const key in _headers) yield [key, _normalizeValue(_headers[key])];
|
||||
}
|
||||
*keys() {
|
||||
const keys = this._node.res.getHeaderNames();
|
||||
for (const key of keys) yield key;
|
||||
}
|
||||
*values() {
|
||||
const values = Object.values(this._node.res.getHeaders());
|
||||
for (const value of values) yield _normalizeValue(value);
|
||||
}
|
||||
[Symbol.iterator]() {
|
||||
return this.entries()[Symbol.iterator]();
|
||||
}
|
||||
get [Symbol.toStringTag]() {
|
||||
return "Headers";
|
||||
}
|
||||
[kNodeInspect]() {
|
||||
return Object.fromEntries(this.entries());
|
||||
}
|
||||
};
|
||||
Object.setPrototypeOf(_Headers.prototype, globalThis.Headers.prototype);
|
||||
return _Headers;
|
||||
})();
|
||||
function _normalizeValue(value) {
|
||||
if (Array.isArray(value)) return value.join(", ");
|
||||
return typeof value === "string" ? value : String(value ?? "");
|
||||
}
|
||||
function validateHeader(name) {
|
||||
if (name[0] === ":") throw new TypeError(`${JSON.stringify(name)} is an invalid header name.`);
|
||||
return name.toLowerCase();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/adapters/_node/response.ts
|
||||
/**
|
||||
* Fast Response for Node.js runtime
|
||||
*
|
||||
* It is faster because in most cases it doesn't create a full Response instance.
|
||||
*/
|
||||
const NodeResponse = /* @__PURE__ */ (() => {
|
||||
const NativeResponse = globalThis.Response;
|
||||
const STATUS_CODES = globalThis.process?.getBuiltinModule("node:http")?.STATUS_CODES || {};
|
||||
class NodeResponse$1 {
|
||||
#body;
|
||||
#init;
|
||||
#headers;
|
||||
#response;
|
||||
constructor(body, init) {
|
||||
this.#body = body;
|
||||
this.#init = init;
|
||||
}
|
||||
get status() {
|
||||
return this.#response?.status || this.#init?.status || 200;
|
||||
}
|
||||
get statusText() {
|
||||
return this.#response?.statusText || this.#init?.statusText || STATUS_CODES[this.status] || "";
|
||||
}
|
||||
get headers() {
|
||||
if (this.#response) return this.#response.headers;
|
||||
if (this.#headers) return this.#headers;
|
||||
const initHeaders = this.#init?.headers;
|
||||
return this.#headers = initHeaders instanceof Headers ? initHeaders : new Headers(initHeaders);
|
||||
}
|
||||
get ok() {
|
||||
if (this.#response) return this.#response.ok;
|
||||
const status = this.status;
|
||||
return status >= 200 && status < 300;
|
||||
}
|
||||
get _response() {
|
||||
if (this.#response) return this.#response;
|
||||
this.#response = new NativeResponse(this.#body, this.#headers ? {
|
||||
...this.#init,
|
||||
headers: this.#headers
|
||||
} : this.#init);
|
||||
this.#init = void 0;
|
||||
this.#headers = void 0;
|
||||
this.#body = void 0;
|
||||
return this.#response;
|
||||
}
|
||||
nodeResponse() {
|
||||
const status = this.status;
|
||||
const statusText = this.statusText;
|
||||
let body;
|
||||
let contentType;
|
||||
let contentLength;
|
||||
if (this.#response) body = this.#response.body;
|
||||
else if (this.#body) if (this.#body instanceof ReadableStream) body = this.#body;
|
||||
else if (typeof this.#body === "string") {
|
||||
body = this.#body;
|
||||
contentType = "text/plain; charset=UTF-8";
|
||||
contentLength = Buffer.byteLength(this.#body);
|
||||
} else if (this.#body instanceof ArrayBuffer) {
|
||||
body = Buffer.from(this.#body);
|
||||
contentLength = this.#body.byteLength;
|
||||
} else if (this.#body instanceof Uint8Array) {
|
||||
body = this.#body;
|
||||
contentLength = this.#body.byteLength;
|
||||
} else if (this.#body instanceof DataView) {
|
||||
body = Buffer.from(this.#body.buffer);
|
||||
contentLength = this.#body.byteLength;
|
||||
} else if (this.#body instanceof Blob) {
|
||||
body = this.#body.stream();
|
||||
contentType = this.#body.type;
|
||||
contentLength = this.#body.size;
|
||||
} else if (typeof this.#body.pipe === "function") body = this.#body;
|
||||
else body = this._response.body;
|
||||
const rawNodeHeaders = [];
|
||||
const initHeaders = this.#init?.headers;
|
||||
const headerEntries = this.#response?.headers || this.#headers || (initHeaders ? Array.isArray(initHeaders) ? initHeaders : initHeaders?.entries ? initHeaders.entries() : Object.entries(initHeaders).map(([k, v]) => [k.toLowerCase(), v]) : void 0);
|
||||
let hasContentTypeHeader;
|
||||
let hasContentLength;
|
||||
if (headerEntries) for (const [key, value] of headerEntries) {
|
||||
if (key === "set-cookie") {
|
||||
for (const setCookie of splitSetCookieString(value)) rawNodeHeaders.push(["set-cookie", setCookie]);
|
||||
continue;
|
||||
}
|
||||
rawNodeHeaders.push([key, value]);
|
||||
if (key === "content-type") hasContentTypeHeader = true;
|
||||
else if (key === "content-length") hasContentLength = true;
|
||||
}
|
||||
if (contentType && !hasContentTypeHeader) rawNodeHeaders.push(["content-type", contentType]);
|
||||
if (contentLength && !hasContentLength) rawNodeHeaders.push(["content-length", String(contentLength)]);
|
||||
this.#init = void 0;
|
||||
this.#headers = void 0;
|
||||
this.#response = void 0;
|
||||
this.#body = void 0;
|
||||
return {
|
||||
status,
|
||||
statusText,
|
||||
headers: rawNodeHeaders,
|
||||
body
|
||||
};
|
||||
}
|
||||
}
|
||||
inheritProps(NodeResponse$1.prototype, NativeResponse.prototype, "_response");
|
||||
Object.setPrototypeOf(NodeResponse$1, NativeResponse);
|
||||
Object.setPrototypeOf(NodeResponse$1.prototype, NativeResponse.prototype);
|
||||
return NodeResponse$1;
|
||||
})();
|
||||
|
||||
//#endregion
|
||||
export { NodeRequestHeaders, NodeResponse, NodeResponseHeaders, inheritProps, kNodeInspect };
|
||||
268
node_modules/srvx/dist/_chunks/types-BtByT9ny.d.mts
generated
vendored
Normal file
268
node_modules/srvx/dist/_chunks/types-BtByT9ny.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
import * as cloudflare_workers0 from "cloudflare:workers";
|
||||
import * as NodeHttp$1 from "node:http";
|
||||
import * as NodeHttps from "node:https";
|
||||
import * as NodeHttp2 from "node:http2";
|
||||
import * as NodeNet from "node:net";
|
||||
import * as Bun from "bun";
|
||||
import * as CF from "@cloudflare/workers-types";
|
||||
|
||||
//#region src/types.d.ts
|
||||
// Utils
|
||||
type MaybePromise<T> = T | Promise<T>;
|
||||
type IsAny<T> = Equal<T, any> extends true ? true : false;
|
||||
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;
|
||||
// ----------------------------------------------------------------------------
|
||||
// srvx API
|
||||
// ----------------------------------------------------------------------------
|
||||
/**
|
||||
* Faster URL constructor with lazy access to pathname and search params (For Node, Deno, and Bun).
|
||||
*/
|
||||
declare const FastURL: typeof globalThis.URL;
|
||||
/**
|
||||
* Faster Response constructor optimized for Node.js (same as Response for other runtimes).
|
||||
*/
|
||||
declare const FastResponse: typeof globalThis.Response;
|
||||
/**
|
||||
* Create a new server instance.
|
||||
*/
|
||||
declare function serve(options: ServerOptions): Server;
|
||||
/**
|
||||
* Web fetch compatible request handler
|
||||
*/
|
||||
type ServerHandler = (request: ServerRequest) => MaybePromise<Response>;
|
||||
type ServerMiddleware = (request: ServerRequest, next: () => Response | Promise<Response>) => Response | Promise<Response>;
|
||||
type ServerPlugin = (server: Server) => void;
|
||||
/**
|
||||
* Server options
|
||||
*/
|
||||
interface ServerOptions {
|
||||
/**
|
||||
* The fetch handler handles incoming requests.
|
||||
*/
|
||||
fetch: ServerHandler;
|
||||
/**
|
||||
* Handle lifecycle errors.
|
||||
*
|
||||
* @note This handler will set built-in Bun and Deno error handler.
|
||||
*/
|
||||
error?: ErrorHandler;
|
||||
/**
|
||||
* Server middleware handlers to run before the main fetch handler.
|
||||
*/
|
||||
middleware?: ServerMiddleware[];
|
||||
/**
|
||||
* Server plugins.
|
||||
*/
|
||||
plugins?: ServerPlugin[];
|
||||
/**
|
||||
* If set to `true`, server will not start listening automatically.
|
||||
*/
|
||||
manual?: boolean;
|
||||
/**
|
||||
* The port server should be listening to.
|
||||
*
|
||||
* Default is read from `PORT` environment variable or will be `3000`.
|
||||
*
|
||||
* **Tip:** You can set the port to `0` to use a random port.
|
||||
*/
|
||||
port?: string | number;
|
||||
/**
|
||||
* The hostname (IP or resolvable host) server listener should bound to.
|
||||
*
|
||||
* When not provided, server with listen to all network interfaces by default.
|
||||
*
|
||||
* **Important:** If you are running a server that is not expected to be exposed to the network, use `hostname: "localhost"`.
|
||||
*/
|
||||
hostname?: string;
|
||||
/**
|
||||
* Enabling this option allows multiple processes to bind to the same port, which is useful for load balancing.
|
||||
*
|
||||
* **Note:** Despite Node.js built-in behavior that has `exclusive` flag (opposite of `reusePort`) enabled by default, srvx uses non-exclusive mode for consistency.
|
||||
*/
|
||||
reusePort?: boolean;
|
||||
/**
|
||||
* The protocol to use for the server.
|
||||
*
|
||||
* Possible values are `http` and `https`.
|
||||
*
|
||||
* If `protocol` is not set, Server will use `http` as the default protocol or `https` if both `tls.cert` and `tls.key` options are provided.
|
||||
*/
|
||||
protocol?: "http" | "https";
|
||||
/**
|
||||
* If set to `true`, server will not print the listening address.
|
||||
*/
|
||||
silent?: boolean;
|
||||
/**
|
||||
* TLS server options.
|
||||
*/
|
||||
tls?: {
|
||||
/**
|
||||
* File path or inlined TLS certificate in PEM format (required).
|
||||
*/
|
||||
cert?: string;
|
||||
/**
|
||||
* File path or inlined TLS private key in PEM format (required).
|
||||
*/
|
||||
key?: string;
|
||||
/**
|
||||
* Passphrase for the private key (optional).
|
||||
*/
|
||||
passphrase?: string;
|
||||
};
|
||||
/**
|
||||
* Node.js server options.
|
||||
*/
|
||||
node?: (NodeHttp$1.ServerOptions | NodeHttps.ServerOptions | NodeHttp2.ServerOptions) & NodeNet.ListenOptions & {
|
||||
http2?: boolean;
|
||||
};
|
||||
/**
|
||||
* Bun server options
|
||||
*
|
||||
* @docs https://bun.sh/docs/api/http
|
||||
*/
|
||||
bun?: Omit<Bun.ServeOptions | Bun.TLSServeOptions, "fetch">;
|
||||
/**
|
||||
* Deno server options
|
||||
*
|
||||
* @docs https://docs.deno.com/api/deno/~/Deno.serve
|
||||
*/
|
||||
deno?: Deno.ServeOptions;
|
||||
/**
|
||||
* Service worker options
|
||||
*/
|
||||
serviceWorker?: {
|
||||
/**
|
||||
* The path to the service worker file to be registered.
|
||||
*/
|
||||
url?: string;
|
||||
/**
|
||||
* The scope of the service worker.
|
||||
*
|
||||
*/
|
||||
scope?: string;
|
||||
};
|
||||
}
|
||||
interface Server<Handler = ServerHandler> {
|
||||
/**
|
||||
* Current runtime name
|
||||
*/
|
||||
readonly runtime: "node" | "deno" | "bun" | "cloudflare" | "service-worker" | "generic";
|
||||
/**
|
||||
* Server options
|
||||
*/
|
||||
readonly options: ServerOptions & {
|
||||
middleware: ServerMiddleware[];
|
||||
};
|
||||
/**
|
||||
* Server URL address.
|
||||
*/
|
||||
readonly url?: string;
|
||||
/**
|
||||
* Node.js context.
|
||||
*/
|
||||
readonly node?: {
|
||||
server?: NodeHttp$1.Server | NodeHttp2.Http2Server;
|
||||
handler: (req: NodeServerRequest, res: NodeServerResponse) => void | Promise<void>;
|
||||
};
|
||||
/**
|
||||
* Bun context.
|
||||
*/
|
||||
readonly bun?: {
|
||||
server?: Bun.Server;
|
||||
};
|
||||
/**
|
||||
* Deno context.
|
||||
*/
|
||||
readonly deno?: {
|
||||
server?: Deno.HttpServer;
|
||||
};
|
||||
/**
|
||||
* Server fetch handler
|
||||
*/
|
||||
readonly fetch: Handler;
|
||||
/**
|
||||
* Start listening for incoming requests.
|
||||
* When `manual` option is enabled, this method needs to be called explicitly to begin accepting connections.
|
||||
*/
|
||||
serve(): void | Promise<Server<Handler>>;
|
||||
/**
|
||||
* Returns a promise that resolves when the server is ready.
|
||||
*/
|
||||
ready(): Promise<Server<Handler>>;
|
||||
/**
|
||||
* Stop listening to prevent new connections from being accepted.
|
||||
*
|
||||
* By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops.
|
||||
*
|
||||
* @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections.
|
||||
* @default false
|
||||
*/
|
||||
close(closeActiveConnections?: boolean): Promise<void>;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
// Request with runtime addons.
|
||||
// ----------------------------------------------------------------------------
|
||||
interface ServerRuntimeContext {
|
||||
name: "node" | "deno" | "bun" | "cloudflare" | (string & {});
|
||||
/**
|
||||
* Underlying Node.js server request info.
|
||||
*/
|
||||
node?: {
|
||||
req: NodeServerRequest;
|
||||
res?: NodeServerResponse;
|
||||
};
|
||||
/**
|
||||
* Underlying Deno server request info.
|
||||
*/
|
||||
deno?: {
|
||||
info: Deno.ServeHandlerInfo<Deno.NetAddr>;
|
||||
};
|
||||
/**
|
||||
* Underlying Bun server request context.
|
||||
*/
|
||||
bun?: {
|
||||
server: Bun.Server;
|
||||
};
|
||||
/**
|
||||
* Underlying Cloudflare request context.
|
||||
*/
|
||||
cloudflare?: {
|
||||
context: CF.ExecutionContext;
|
||||
env: IsAny<typeof cloudflare_workers0> extends true ? Record<string, unknown> : typeof cloudflare_workers0.env;
|
||||
};
|
||||
}
|
||||
interface ServerRequestContext {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
interface ServerRequest extends Request {
|
||||
/**
|
||||
* Runtime specific request context.
|
||||
*/
|
||||
runtime?: ServerRuntimeContext;
|
||||
/**
|
||||
* IP address of the client.
|
||||
*/
|
||||
ip?: string | undefined;
|
||||
/**
|
||||
* Arbitrary context related to the request.
|
||||
*/
|
||||
context?: ServerRequestContext;
|
||||
/**
|
||||
* Tell the runtime about an ongoing operation that shouldn't close until the promise resolves.
|
||||
*/
|
||||
waitUntil?: (promise: Promise<unknown>) => void | Promise<void>;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
// Different handler types
|
||||
// ----------------------------------------------------------------------------
|
||||
type FetchHandler = (request: Request) => Response | Promise<Response>;
|
||||
type ErrorHandler = (error: unknown) => Response | Promise<Response>;
|
||||
type BunFetchHandler = (request: Request, server?: Bun.Server) => Response | Promise<Response>;
|
||||
type DenoFetchHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.NetAddr>) => Response | Promise<Response>;
|
||||
type NodeServerRequest = NodeHttp$1.IncomingMessage | NodeHttp2.Http2ServerRequest;
|
||||
type NodeServerResponse = NodeHttp$1.ServerResponse | NodeHttp2.Http2ServerResponse;
|
||||
type NodeHttpHandler = (req: NodeServerRequest, res: NodeServerResponse) => void | Promise<void>;
|
||||
type NodeHTTPMiddleware = (req: NodeServerRequest, res: NodeServerResponse, next: (error?: Error) => void) => unknown | Promise<unknown>;
|
||||
type CloudflareFetchHandler = CF.ExportedHandlerFetchHandler;
|
||||
//#endregion
|
||||
export { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTPMiddleware, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, serve };
|
||||
23
node_modules/srvx/dist/adapters/bun.d.mts
generated
vendored
Normal file
23
node_modules/srvx/dist/adapters/bun.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { BunFetchHandler, Server, ServerOptions } from "../_chunks/types-BtByT9ny.mjs";
|
||||
import { FastURL$2 as FastURL } from "../_chunks/_url-D8u5OAto.mjs";
|
||||
import * as bun from "bun";
|
||||
|
||||
//#region src/adapters/bun.d.ts
|
||||
declare const FastResponse: typeof globalThis.Response;
|
||||
declare function serve(options: ServerOptions): BunServer;
|
||||
// https://bun.sh/docs/api/http
|
||||
declare class BunServer implements Server<BunFetchHandler> {
|
||||
#private;
|
||||
readonly runtime = "bun";
|
||||
readonly options: Server["options"];
|
||||
readonly bun: Server["bun"];
|
||||
readonly serveOptions: bun.ServeOptions | bun.TLSServeOptions;
|
||||
readonly fetch: BunFetchHandler;
|
||||
constructor(options: ServerOptions);
|
||||
serve(): Promise<this>;
|
||||
get url(): string | undefined;
|
||||
ready(): Promise<this>;
|
||||
close(closeAll?: boolean): Promise<void>;
|
||||
}
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
81
node_modules/srvx/dist/adapters/bun.mjs
generated
vendored
Normal file
81
node_modules/srvx/dist/adapters/bun.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "../_chunks/_utils-DRF_4b_y.mjs";
|
||||
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
|
||||
import { FastURL$1 as FastURL } from "../_chunks/_url-CdE4ce6F.mjs";
|
||||
|
||||
//#region src/adapters/bun.ts
|
||||
const FastResponse = Response;
|
||||
function serve(options) {
|
||||
return new BunServer(options);
|
||||
}
|
||||
var BunServer = class {
|
||||
runtime = "bun";
|
||||
options;
|
||||
bun = {};
|
||||
serveOptions;
|
||||
fetch;
|
||||
#wait;
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...options,
|
||||
middleware: [...options.middleware || []]
|
||||
};
|
||||
for (const plugin of options.plugins || []) plugin(this);
|
||||
const fetchHandler = wrapFetch(this);
|
||||
this.#wait = createWaitUntil();
|
||||
this.fetch = (request, server) => {
|
||||
Object.defineProperties(request, {
|
||||
waitUntil: { value: this.#wait.waitUntil },
|
||||
runtime: {
|
||||
enumerable: true,
|
||||
value: {
|
||||
name: "bun",
|
||||
bun: { server }
|
||||
}
|
||||
},
|
||||
ip: {
|
||||
enumerable: true,
|
||||
get() {
|
||||
return server?.requestIP(request)?.address;
|
||||
}
|
||||
}
|
||||
});
|
||||
return fetchHandler(request);
|
||||
};
|
||||
const tls = resolveTLSOptions(this.options);
|
||||
this.serveOptions = {
|
||||
...resolvePortAndHost(this.options),
|
||||
reusePort: this.options.reusePort,
|
||||
error: this.options.error,
|
||||
...this.options.bun,
|
||||
tls: {
|
||||
cert: tls?.cert,
|
||||
key: tls?.key,
|
||||
passphrase: tls?.passphrase,
|
||||
...this.options.bun?.tls
|
||||
},
|
||||
fetch: this.fetch
|
||||
};
|
||||
if (!options.manual) this.serve();
|
||||
}
|
||||
serve() {
|
||||
if (!this.bun.server) this.bun.server = Bun.serve(this.serveOptions);
|
||||
printListening(this.options, this.url);
|
||||
return Promise.resolve(this);
|
||||
}
|
||||
get url() {
|
||||
const server = this.bun?.server;
|
||||
if (!server) return;
|
||||
const address = server.address;
|
||||
if (address) return fmtURL(address.address, address.port, server.protocol === "https");
|
||||
return server.url.href;
|
||||
}
|
||||
ready() {
|
||||
return Promise.resolve(this);
|
||||
}
|
||||
async close(closeAll) {
|
||||
await Promise.all([this.#wait.wait(), Promise.resolve(this.bun?.server?.stop(closeAll))]);
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
9
node_modules/srvx/dist/adapters/cloudflare.d.mts
generated
vendored
Normal file
9
node_modules/srvx/dist/adapters/cloudflare.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { Server, ServerOptions } from "../_chunks/types-BtByT9ny.mjs";
|
||||
import * as CF from "@cloudflare/workers-types";
|
||||
|
||||
//#region src/adapters/cloudflare.d.ts
|
||||
declare const FastURL: typeof globalThis.URL;
|
||||
declare const FastResponse: typeof globalThis.Response;
|
||||
declare function serve(options: ServerOptions): Server<CF.ExportedHandlerFetchHandler>;
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
62
node_modules/srvx/dist/adapters/cloudflare.mjs
generated
vendored
Normal file
62
node_modules/srvx/dist/adapters/cloudflare.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
|
||||
import { errorPlugin } from "../_chunks/_plugins-DOhVIkXu.mjs";
|
||||
|
||||
//#region src/adapters/cloudflare.ts
|
||||
const FastURL = URL;
|
||||
const FastResponse = Response;
|
||||
function serve(options) {
|
||||
return new CloudflareServer(options);
|
||||
}
|
||||
var CloudflareServer = class {
|
||||
runtime = "cloudflare";
|
||||
options;
|
||||
serveOptions;
|
||||
fetch;
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...options,
|
||||
middleware: [...options.middleware || []]
|
||||
};
|
||||
for (const plugin of options.plugins || []) plugin(this);
|
||||
errorPlugin(this);
|
||||
const fetchHandler = wrapFetch(this);
|
||||
this.fetch = (request, env, context) => {
|
||||
Object.defineProperties(request, {
|
||||
waitUntil: { value: context.waitUntil.bind(context) },
|
||||
runtime: {
|
||||
enumerable: true,
|
||||
value: {
|
||||
name: "cloudflare",
|
||||
cloudflare: {
|
||||
env,
|
||||
context
|
||||
}
|
||||
}
|
||||
},
|
||||
ip: {
|
||||
enumerable: true,
|
||||
get() {
|
||||
return request.headers.get("cf-connecting-ip");
|
||||
}
|
||||
}
|
||||
});
|
||||
return fetchHandler(request);
|
||||
};
|
||||
this.serveOptions = { fetch: this.fetch };
|
||||
if (!options.manual) this.serve();
|
||||
}
|
||||
serve() {
|
||||
addEventListener("fetch", (event) => {
|
||||
event.respondWith(this.fetch(event.request, {}, event));
|
||||
});
|
||||
}
|
||||
ready() {
|
||||
return Promise.resolve().then(() => this);
|
||||
}
|
||||
close() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
22
node_modules/srvx/dist/adapters/deno.d.mts
generated
vendored
Normal file
22
node_modules/srvx/dist/adapters/deno.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { DenoFetchHandler, Server, ServerOptions } from "../_chunks/types-BtByT9ny.mjs";
|
||||
import { FastURL$2 as FastURL } from "../_chunks/_url-D8u5OAto.mjs";
|
||||
|
||||
//#region src/adapters/deno.d.ts
|
||||
declare const FastResponse: typeof globalThis.Response;
|
||||
declare function serve(options: ServerOptions): DenoServer;
|
||||
// https://docs.deno.com/api/deno/~/Deno.serve
|
||||
declare class DenoServer implements Server<DenoFetchHandler> {
|
||||
#private;
|
||||
readonly runtime = "deno";
|
||||
readonly options: Server["options"];
|
||||
readonly deno: Server["deno"];
|
||||
readonly serveOptions: Deno.ServeTcpOptions | (Deno.ServeTcpOptions & Deno.TlsCertifiedKeyPem);
|
||||
readonly fetch: DenoFetchHandler;
|
||||
constructor(options: ServerOptions);
|
||||
serve(): Promise<this>;
|
||||
get url(): string | undefined;
|
||||
ready(): Promise<Server>;
|
||||
close(): Promise<void>;
|
||||
}
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
90
node_modules/srvx/dist/adapters/deno.mjs
generated
vendored
Normal file
90
node_modules/srvx/dist/adapters/deno.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "../_chunks/_utils-DRF_4b_y.mjs";
|
||||
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
|
||||
import { FastURL$1 as FastURL } from "../_chunks/_url-CdE4ce6F.mjs";
|
||||
|
||||
//#region src/adapters/deno.ts
|
||||
const FastResponse = Response;
|
||||
function serve(options) {
|
||||
return new DenoServer(options);
|
||||
}
|
||||
var DenoServer = class {
|
||||
runtime = "deno";
|
||||
options;
|
||||
deno = {};
|
||||
serveOptions;
|
||||
fetch;
|
||||
#listeningPromise;
|
||||
#listeningInfo;
|
||||
#wait;
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...options,
|
||||
middleware: [...options.middleware || []]
|
||||
};
|
||||
for (const plugin of options.plugins || []) plugin(this);
|
||||
const fetchHandler = wrapFetch(this);
|
||||
this.#wait = createWaitUntil();
|
||||
this.fetch = (request, info) => {
|
||||
Object.defineProperties(request, {
|
||||
waitUntil: { value: this.#wait.waitUntil },
|
||||
runtime: {
|
||||
enumerable: true,
|
||||
value: {
|
||||
name: "deno",
|
||||
deno: {
|
||||
info,
|
||||
server: this.deno?.server
|
||||
}
|
||||
}
|
||||
},
|
||||
ip: {
|
||||
enumerable: true,
|
||||
get() {
|
||||
return (info?.remoteAddr)?.hostname;
|
||||
}
|
||||
}
|
||||
});
|
||||
return fetchHandler(request);
|
||||
};
|
||||
const tls = resolveTLSOptions(this.options);
|
||||
this.serveOptions = {
|
||||
...resolvePortAndHost(this.options),
|
||||
reusePort: this.options.reusePort,
|
||||
onError: this.options.error,
|
||||
...tls ? {
|
||||
key: tls.key,
|
||||
cert: tls.cert,
|
||||
passphrase: tls.passphrase
|
||||
} : {},
|
||||
...this.options.deno
|
||||
};
|
||||
if (!options.manual) this.serve();
|
||||
}
|
||||
serve() {
|
||||
if (this.deno?.server) return Promise.resolve(this.#listeningPromise).then(() => this);
|
||||
const onListenPromise = Promise.withResolvers();
|
||||
this.#listeningPromise = onListenPromise.promise;
|
||||
this.deno.server = Deno.serve({
|
||||
...this.serveOptions,
|
||||
onListen: (info) => {
|
||||
this.#listeningInfo = info;
|
||||
if (this.options.deno?.onListen) this.options.deno.onListen(info);
|
||||
printListening(this.options, this.url);
|
||||
onListenPromise.resolve();
|
||||
}
|
||||
}, this.fetch);
|
||||
return Promise.resolve(this.#listeningPromise).then(() => this);
|
||||
}
|
||||
get url() {
|
||||
return this.#listeningInfo ? fmtURL(this.#listeningInfo.hostname, this.#listeningInfo.port, !!this.serveOptions.cert) : void 0;
|
||||
}
|
||||
ready() {
|
||||
return Promise.resolve(this.#listeningPromise).then(() => this);
|
||||
}
|
||||
async close() {
|
||||
await Promise.all([this.#wait.wait(), Promise.resolve(this.deno?.server?.shutdown())]);
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
8
node_modules/srvx/dist/adapters/generic.d.mts
generated
vendored
Normal file
8
node_modules/srvx/dist/adapters/generic.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { Server, ServerOptions } from "../_chunks/types-BtByT9ny.mjs";
|
||||
|
||||
//#region src/adapters/generic.d.ts
|
||||
declare const FastURL: typeof globalThis.URL;
|
||||
declare const FastResponse: typeof globalThis.Response;
|
||||
declare function serve(options: ServerOptions): Server;
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
40
node_modules/srvx/dist/adapters/generic.mjs
generated
vendored
Normal file
40
node_modules/srvx/dist/adapters/generic.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { createWaitUntil } from "../_chunks/_utils-DRF_4b_y.mjs";
|
||||
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
|
||||
import { errorPlugin } from "../_chunks/_plugins-DOhVIkXu.mjs";
|
||||
|
||||
//#region src/adapters/generic.ts
|
||||
const FastURL = URL;
|
||||
const FastResponse = Response;
|
||||
function serve(options) {
|
||||
return new GenericServer(options);
|
||||
}
|
||||
var GenericServer = class {
|
||||
runtime = "generic";
|
||||
options;
|
||||
fetch;
|
||||
#wait;
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...options,
|
||||
middleware: [...options.middleware || []]
|
||||
};
|
||||
for (const plugin of options.plugins || []) plugin(this);
|
||||
errorPlugin(this);
|
||||
this.#wait = createWaitUntil();
|
||||
const fetchHandler = wrapFetch(this);
|
||||
this.fetch = (request) => {
|
||||
Object.defineProperties(request, { waitUntil: { value: this.#wait.waitUntil } });
|
||||
return Promise.resolve(fetchHandler(request));
|
||||
};
|
||||
}
|
||||
serve() {}
|
||||
ready() {
|
||||
return Promise.resolve(this);
|
||||
}
|
||||
async close() {
|
||||
await this.#wait.wait();
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
58
node_modules/srvx/dist/adapters/node.d.mts
generated
vendored
Normal file
58
node_modules/srvx/dist/adapters/node.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { FetchHandler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerOptions, ServerRequest } from "../_chunks/types-BtByT9ny.mjs";
|
||||
import { FastURL$2 as FastURL } from "../_chunks/_url-D8u5OAto.mjs";
|
||||
import NodeHttp from "node:http";
|
||||
import { Readable } from "node:stream";
|
||||
|
||||
//#region src/adapters/_node/request.d.ts
|
||||
type NodeRequestContext = {
|
||||
req: NodeServerRequest;
|
||||
res?: NodeServerResponse;
|
||||
};
|
||||
declare const NodeRequest: {
|
||||
new (nodeCtx: NodeRequestContext): ServerRequest;
|
||||
};
|
||||
//#endregion
|
||||
//#region src/adapters/_node/headers.d.ts
|
||||
type NodeRequestHeaders = InstanceType<typeof NodeRequestHeaders>;
|
||||
declare const NodeRequestHeaders: {
|
||||
new (nodeCtx: {
|
||||
req: NodeServerRequest;
|
||||
res?: NodeServerResponse;
|
||||
}): globalThis.Headers;
|
||||
};
|
||||
declare const NodeResponseHeaders: {
|
||||
new (nodeCtx: {
|
||||
req?: NodeServerRequest;
|
||||
res: NodeServerResponse;
|
||||
}): globalThis.Headers;
|
||||
};
|
||||
//#endregion
|
||||
//#region src/adapters/_node/response.d.ts
|
||||
// prettier-ignore
|
||||
type PreparedNodeResponseBody = string | Buffer | Uint8Array | DataView | ReadableStream | Readable | undefined | null;
|
||||
interface PreparedNodeResponse {
|
||||
status: number;
|
||||
statusText: string;
|
||||
headers: NodeHttp.OutgoingHttpHeader[];
|
||||
body: PreparedNodeResponseBody;
|
||||
}
|
||||
/**
|
||||
* Fast Response for Node.js runtime
|
||||
*
|
||||
* It is faster because in most cases it doesn't create a full Response instance.
|
||||
*/
|
||||
declare const NodeResponse: {
|
||||
new (body?: BodyInit | null, init?: ResponseInit): globalThis.Response & {
|
||||
readonly nodeResponse: () => PreparedNodeResponse;
|
||||
};
|
||||
};
|
||||
type NodeResponse = InstanceType<typeof NodeResponse>;
|
||||
//#endregion
|
||||
//#region src/adapters/_node/send.d.ts
|
||||
declare function sendNodeResponse(nodeRes: NodeServerResponse, webRes: Response | NodeResponse): Promise<void>;
|
||||
//#endregion
|
||||
//#region src/adapters/node.d.ts
|
||||
declare function serve(options: ServerOptions): Server;
|
||||
declare function toNodeHandler(fetchHandler: FetchHandler): NodeHttpHandler;
|
||||
//#endregion
|
||||
export { NodeResponse as FastResponse, FastURL, NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, sendNodeResponse, serve, toNodeHandler };
|
||||
398
node_modules/srvx/dist/adapters/node.mjs
generated
vendored
Normal file
398
node_modules/srvx/dist/adapters/node.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "../_chunks/_utils-DRF_4b_y.mjs";
|
||||
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
|
||||
import { FastURL$1 as FastURL } from "../_chunks/_url-CdE4ce6F.mjs";
|
||||
import { NodeRequestHeaders, NodeResponse, NodeResponseHeaders, inheritProps, kNodeInspect } from "../_chunks/response-6LJL3Qlz.mjs";
|
||||
import { errorPlugin } from "../_chunks/_plugins-DOhVIkXu.mjs";
|
||||
import { splitSetCookieString } from "cookie-es";
|
||||
|
||||
//#region src/adapters/_node/send.ts
|
||||
async function sendNodeResponse(nodeRes, webRes) {
|
||||
if (!webRes) {
|
||||
nodeRes.statusCode = 500;
|
||||
return endNodeResponse(nodeRes);
|
||||
}
|
||||
if (webRes.nodeResponse) {
|
||||
const res = webRes.nodeResponse();
|
||||
writeHead(nodeRes, res.status, res.statusText, res.headers.flat());
|
||||
if (res.body) {
|
||||
if (res.body instanceof ReadableStream) return streamBody(res.body, nodeRes);
|
||||
else if (typeof res.body?.pipe === "function") {
|
||||
res.body.pipe(nodeRes);
|
||||
return new Promise((resolve) => nodeRes.on("close", resolve));
|
||||
}
|
||||
nodeRes.write(res.body);
|
||||
}
|
||||
return endNodeResponse(nodeRes);
|
||||
}
|
||||
const headerEntries = [];
|
||||
for (const [key, value] of webRes.headers) if (key === "set-cookie") for (const setCookie of splitSetCookieString(value)) headerEntries.push(["set-cookie", setCookie]);
|
||||
else headerEntries.push([key, value]);
|
||||
writeHead(nodeRes, webRes.status, webRes.statusText, headerEntries.flat());
|
||||
return webRes.body ? streamBody(webRes.body, nodeRes) : endNodeResponse(nodeRes);
|
||||
}
|
||||
function writeHead(nodeRes, status, statusText, headers) {
|
||||
if (!nodeRes.headersSent) if (nodeRes.req?.httpVersion === "2.0") nodeRes.writeHead(status, headers.flat());
|
||||
else nodeRes.writeHead(status, statusText, headers.flat());
|
||||
}
|
||||
function endNodeResponse(nodeRes) {
|
||||
return new Promise((resolve) => nodeRes.end(resolve));
|
||||
}
|
||||
function streamBody(stream, nodeRes) {
|
||||
if (nodeRes.destroyed) {
|
||||
stream.cancel();
|
||||
return;
|
||||
}
|
||||
const reader = stream.getReader();
|
||||
function streamCancel(error) {
|
||||
reader.cancel(error).catch(() => {});
|
||||
if (error) nodeRes.destroy(error);
|
||||
}
|
||||
function streamHandle({ done, value }) {
|
||||
try {
|
||||
if (done) nodeRes.end();
|
||||
else if (nodeRes.write(value)) reader.read().then(streamHandle, streamCancel);
|
||||
else nodeRes.once("drain", () => reader.read().then(streamHandle, streamCancel));
|
||||
} catch (error) {
|
||||
streamCancel(error instanceof Error ? error : void 0);
|
||||
}
|
||||
}
|
||||
nodeRes.on("close", streamCancel);
|
||||
nodeRes.on("error", streamCancel);
|
||||
reader.read().then(streamHandle, streamCancel);
|
||||
return reader.closed.finally(() => {
|
||||
nodeRes.off("close", streamCancel);
|
||||
nodeRes.off("error", streamCancel);
|
||||
});
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/adapters/_node/url.ts
|
||||
const NodeRequestURL = /* @__PURE__ */ (() => {
|
||||
const _URL = class URL {
|
||||
_node;
|
||||
_hash = "";
|
||||
_username = "";
|
||||
_password = "";
|
||||
_protocol;
|
||||
_hostname;
|
||||
_port;
|
||||
_pathname;
|
||||
_search;
|
||||
_searchParams;
|
||||
constructor(nodeCtx) {
|
||||
this._node = nodeCtx;
|
||||
}
|
||||
get hash() {
|
||||
return this._hash;
|
||||
}
|
||||
set hash(value) {
|
||||
this._hash = value;
|
||||
}
|
||||
get username() {
|
||||
return this._username;
|
||||
}
|
||||
set username(value) {
|
||||
this._username = value;
|
||||
}
|
||||
get password() {
|
||||
return this._password;
|
||||
}
|
||||
set password(value) {
|
||||
this._password = value;
|
||||
}
|
||||
get host() {
|
||||
return this._node.req.headers.host || this._node.req.headers[":authority"] || "";
|
||||
}
|
||||
set host(value) {
|
||||
this._hostname = void 0;
|
||||
this._port = void 0;
|
||||
this._node.req.headers.host = value;
|
||||
}
|
||||
get hostname() {
|
||||
if (this._hostname === void 0) {
|
||||
const [hostname, port] = parseHost(this._node.req.headers.host);
|
||||
if (this._port === void 0 && port) this._port = String(Number.parseInt(port) || "");
|
||||
this._hostname = hostname || "localhost";
|
||||
}
|
||||
return this._hostname;
|
||||
}
|
||||
set hostname(value) {
|
||||
this._hostname = value;
|
||||
}
|
||||
get port() {
|
||||
if (this._port === void 0) {
|
||||
const [hostname, port] = parseHost(this._node.req.headers.host);
|
||||
if (this._hostname === void 0 && hostname) this._hostname = hostname;
|
||||
this._port = port || String(this._node.req.socket?.localPort || "");
|
||||
}
|
||||
return this._port;
|
||||
}
|
||||
set port(value) {
|
||||
this._port = String(Number.parseInt(value) || "");
|
||||
}
|
||||
get pathname() {
|
||||
if (this._pathname === void 0) {
|
||||
const [pathname, search] = parsePath(this._node.req.url || "/");
|
||||
this._pathname = pathname;
|
||||
if (this._search === void 0) this._search = search;
|
||||
}
|
||||
return this._pathname;
|
||||
}
|
||||
set pathname(value) {
|
||||
if (value[0] !== "/") value = "/" + value;
|
||||
if (value === this._pathname) return;
|
||||
this._pathname = value;
|
||||
this._node.req.url = value + this.search;
|
||||
}
|
||||
get search() {
|
||||
if (this._search === void 0) {
|
||||
const [pathname, search] = parsePath(this._node.req.url || "/");
|
||||
this._search = search;
|
||||
if (this._pathname === void 0) this._pathname = pathname;
|
||||
}
|
||||
return this._search;
|
||||
}
|
||||
set search(value) {
|
||||
if (value === "?") value = "";
|
||||
else if (value && value[0] !== "?") value = "?" + value;
|
||||
if (value === this._search) return;
|
||||
this._search = value;
|
||||
this._searchParams = void 0;
|
||||
this._node.req.url = this.pathname + value;
|
||||
}
|
||||
get searchParams() {
|
||||
if (!this._searchParams) this._searchParams = new URLSearchParams(this.search);
|
||||
return this._searchParams;
|
||||
}
|
||||
set searchParams(value) {
|
||||
this._searchParams = value;
|
||||
this._search = value.toString();
|
||||
}
|
||||
get protocol() {
|
||||
if (!this._protocol) this._protocol = this._node.req.socket?.encrypted || this._node.req.headers["x-forwarded-proto"] === "https" ? "https:" : "http:";
|
||||
return this._protocol;
|
||||
}
|
||||
set protocol(value) {
|
||||
this._protocol = value;
|
||||
}
|
||||
get origin() {
|
||||
return `${this.protocol}//${this.host}`;
|
||||
}
|
||||
set origin(_value) {}
|
||||
get href() {
|
||||
return `${this.protocol}//${this.host}${this.pathname}${this.search}`;
|
||||
}
|
||||
set href(value) {
|
||||
const _url = new globalThis.URL(value);
|
||||
this._protocol = _url.protocol;
|
||||
this.username = _url.username;
|
||||
this.password = _url.password;
|
||||
this._hostname = _url.hostname;
|
||||
this._port = _url.port;
|
||||
this.pathname = _url.pathname;
|
||||
this.search = _url.search;
|
||||
this.hash = _url.hash;
|
||||
}
|
||||
toString() {
|
||||
return this.href;
|
||||
}
|
||||
toJSON() {
|
||||
return this.href;
|
||||
}
|
||||
get [Symbol.toStringTag]() {
|
||||
return "URL";
|
||||
}
|
||||
[kNodeInspect]() {
|
||||
return this.href;
|
||||
}
|
||||
};
|
||||
Object.setPrototypeOf(_URL.prototype, globalThis.URL.prototype);
|
||||
return _URL;
|
||||
})();
|
||||
function parsePath(input) {
|
||||
const url = (input || "/").replace(/\\/g, "/");
|
||||
const qIndex = url.indexOf("?");
|
||||
if (qIndex === -1) return [url, ""];
|
||||
return [url.slice(0, qIndex), url.slice(qIndex)];
|
||||
}
|
||||
function parseHost(host) {
|
||||
const s = (host || "").split(":");
|
||||
return [s[0], String(Number.parseInt(s[1]) || "")];
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/adapters/_node/request.ts
|
||||
const NodeRequest = /* @__PURE__ */ (() => {
|
||||
const { Readable } = process.getBuiltinModule("node:stream");
|
||||
const NativeRequest = globalThis._Request ??= globalThis.Request;
|
||||
const PatchedRequest = class Request extends NativeRequest {
|
||||
static _srvx = true;
|
||||
constructor(input, options) {
|
||||
if (typeof input === "object" && "_request" in input) input = input._request;
|
||||
if ((options?.body)?.getReader !== void 0) options.duplex ??= "half";
|
||||
super(input, options);
|
||||
}
|
||||
};
|
||||
if (!globalThis.Request._srvx) globalThis.Request = PatchedRequest;
|
||||
class NodeRequest$1 {
|
||||
_node;
|
||||
_url;
|
||||
runtime;
|
||||
#request;
|
||||
#headers;
|
||||
#abortSignal;
|
||||
constructor(ctx) {
|
||||
this._node = ctx;
|
||||
this._url = new NodeRequestURL({ req: ctx.req });
|
||||
this.runtime = {
|
||||
name: "node",
|
||||
node: ctx
|
||||
};
|
||||
}
|
||||
get ip() {
|
||||
return this._node.req.socket?.remoteAddress;
|
||||
}
|
||||
get method() {
|
||||
return this._node.req.method || "GET";
|
||||
}
|
||||
get url() {
|
||||
return this._url.href;
|
||||
}
|
||||
get headers() {
|
||||
return this.#headers ||= new NodeRequestHeaders(this._node);
|
||||
}
|
||||
get signal() {
|
||||
if (!this.#abortSignal) {
|
||||
this.#abortSignal = new AbortController();
|
||||
this._node.req.once("close", () => {
|
||||
this.#abortSignal?.abort();
|
||||
});
|
||||
}
|
||||
return this.#abortSignal.signal;
|
||||
}
|
||||
get _request() {
|
||||
if (!this.#request) {
|
||||
const method = this.method;
|
||||
const hasBody = !(method === "GET" || method === "HEAD");
|
||||
this.#request = new PatchedRequest(this.url, {
|
||||
method,
|
||||
headers: this.headers,
|
||||
signal: this.signal,
|
||||
body: hasBody ? Readable.toWeb(this._node.req) : void 0
|
||||
});
|
||||
}
|
||||
return this.#request;
|
||||
}
|
||||
}
|
||||
inheritProps(NodeRequest$1.prototype, NativeRequest.prototype, "_request");
|
||||
Object.setPrototypeOf(NodeRequest$1.prototype, PatchedRequest.prototype);
|
||||
return NodeRequest$1;
|
||||
})();
|
||||
|
||||
//#endregion
|
||||
//#region src/adapters/node.ts
|
||||
function serve(options) {
|
||||
return new NodeServer(options);
|
||||
}
|
||||
function toNodeHandler(fetchHandler) {
|
||||
return (nodeReq, nodeRes) => {
|
||||
const request = new NodeRequest({
|
||||
req: nodeReq,
|
||||
res: nodeRes
|
||||
});
|
||||
const res = fetchHandler(request);
|
||||
return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
|
||||
};
|
||||
}
|
||||
var NodeServer = class {
|
||||
runtime = "node";
|
||||
options;
|
||||
node;
|
||||
serveOptions;
|
||||
fetch;
|
||||
#isSecure;
|
||||
#listeningPromise;
|
||||
#wait;
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...options,
|
||||
middleware: [...options.middleware || []]
|
||||
};
|
||||
for (const plugin of options.plugins || []) plugin(this);
|
||||
errorPlugin(this);
|
||||
const fetchHandler = this.fetch = wrapFetch(this);
|
||||
this.#wait = createWaitUntil();
|
||||
const handler = (nodeReq, nodeRes) => {
|
||||
const request = new NodeRequest({
|
||||
req: nodeReq,
|
||||
res: nodeRes
|
||||
});
|
||||
request.waitUntil = this.#wait.waitUntil;
|
||||
const res = fetchHandler(request);
|
||||
return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
|
||||
};
|
||||
const tls = resolveTLSOptions(this.options);
|
||||
const { port, hostname: host } = resolvePortAndHost(this.options);
|
||||
this.serveOptions = {
|
||||
port,
|
||||
host,
|
||||
exclusive: !this.options.reusePort,
|
||||
...tls ? {
|
||||
cert: tls.cert,
|
||||
key: tls.key,
|
||||
passphrase: tls.passphrase
|
||||
} : {},
|
||||
...this.options.node
|
||||
};
|
||||
let server;
|
||||
this.#isSecure = !!this.serveOptions.cert && this.options.protocol !== "http";
|
||||
const isHttp2 = this.options.node?.http2 ?? this.#isSecure;
|
||||
if (isHttp2) if (this.#isSecure) {
|
||||
const { createSecureServer } = process.getBuiltinModule("node:http2");
|
||||
server = createSecureServer({
|
||||
allowHTTP1: true,
|
||||
...this.serveOptions
|
||||
}, handler);
|
||||
} else throw new Error("node.http2 option requires tls certificate!");
|
||||
else if (this.#isSecure) {
|
||||
const { createServer } = process.getBuiltinModule("node:https");
|
||||
server = createServer(this.serveOptions, handler);
|
||||
} else {
|
||||
const { createServer } = process.getBuiltinModule("node:http");
|
||||
server = createServer(this.serveOptions, handler);
|
||||
}
|
||||
this.node = {
|
||||
server,
|
||||
handler
|
||||
};
|
||||
if (!options.manual) this.serve();
|
||||
}
|
||||
serve() {
|
||||
if (this.#listeningPromise) return Promise.resolve(this.#listeningPromise).then(() => this);
|
||||
this.#listeningPromise = new Promise((resolve) => {
|
||||
this.node.server.listen(this.serveOptions, () => {
|
||||
printListening(this.options, this.url);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
get url() {
|
||||
const addr = this.node?.server?.address();
|
||||
if (!addr) return;
|
||||
return typeof addr === "string" ? addr : fmtURL(addr.address, addr.port, this.#isSecure);
|
||||
}
|
||||
ready() {
|
||||
return Promise.resolve(this.#listeningPromise).then(() => this);
|
||||
}
|
||||
async close(closeAll) {
|
||||
await Promise.all([this.#wait.wait(), new Promise((resolve, reject) => {
|
||||
const server = this.node?.server;
|
||||
if (!server) return resolve();
|
||||
if (closeAll && "closeAllConnections" in server) server.closeAllConnections();
|
||||
server.close((error) => error ? reject(error) : resolve());
|
||||
})]);
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { NodeResponse as FastResponse, FastURL, NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, sendNodeResponse, serve, toNodeHandler };
|
||||
9
node_modules/srvx/dist/adapters/service-worker.d.mts
generated
vendored
Normal file
9
node_modules/srvx/dist/adapters/service-worker.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { Server, ServerOptions, ServerRequest } from "../_chunks/types-BtByT9ny.mjs";
|
||||
|
||||
//#region src/adapters/service-worker.d.ts
|
||||
declare const FastURL: typeof globalThis.URL;
|
||||
declare const FastResponse: typeof globalThis.Response;
|
||||
type ServiceWorkerHandler = (request: ServerRequest, event: FetchEvent) => Response | Promise<Response>;
|
||||
declare function serve(options: ServerOptions): Server<ServiceWorkerHandler>;
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, ServiceWorkerHandler, serve };
|
||||
81
node_modules/srvx/dist/adapters/service-worker.mjs
generated
vendored
Normal file
81
node_modules/srvx/dist/adapters/service-worker.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import { wrapFetch } from "../_chunks/_middleware-BvRR7B4M.mjs";
|
||||
import { errorPlugin } from "../_chunks/_plugins-DOhVIkXu.mjs";
|
||||
|
||||
//#region src/adapters/service-worker.ts
|
||||
const FastURL = URL;
|
||||
const FastResponse = Response;
|
||||
const isBrowserWindow = typeof window !== "undefined" && typeof navigator !== "undefined";
|
||||
const isServiceWorker = /* @__PURE__ */ (() => typeof self !== "undefined" && "skipWaiting" in self)();
|
||||
function serve(options) {
|
||||
return new ServiceWorkerServer(options);
|
||||
}
|
||||
var ServiceWorkerServer = class {
|
||||
runtime = "service-worker";
|
||||
options;
|
||||
fetch;
|
||||
#fetchListener;
|
||||
#listeningPromise;
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
...options,
|
||||
middleware: [...options.middleware || []]
|
||||
};
|
||||
for (const plugin of options.plugins || []) plugin(this);
|
||||
errorPlugin(this);
|
||||
const fetchHandler = wrapFetch(this);
|
||||
this.fetch = (request, event) => {
|
||||
Object.defineProperties(request, { runtime: {
|
||||
enumerable: true,
|
||||
value: {
|
||||
name: "service-worker",
|
||||
serviceWorker: { event }
|
||||
}
|
||||
} });
|
||||
return Promise.resolve(fetchHandler(request));
|
||||
};
|
||||
if (!options.manual) this.serve();
|
||||
}
|
||||
serve() {
|
||||
if (isBrowserWindow) {
|
||||
if (!navigator.serviceWorker) throw new Error("Service worker is not supported in the current window.");
|
||||
const swURL = this.options.serviceWorker?.url;
|
||||
if (!swURL) throw new Error("Service worker URL is not provided. Please set the `serviceWorker.url` serve option or manually register.");
|
||||
this.#listeningPromise = navigator.serviceWorker.register(swURL, {
|
||||
type: "module",
|
||||
scope: this.options.serviceWorker?.scope
|
||||
}).then((registration) => {
|
||||
if (registration.active) location.replace(location.href);
|
||||
else registration.addEventListener("updatefound", () => {
|
||||
location.replace(location.href);
|
||||
});
|
||||
});
|
||||
} else if (isServiceWorker) {
|
||||
this.#fetchListener = async (event) => {
|
||||
if (/\/[^/]*\.[a-zA-Z0-9]+$/.test(new URL(event.request.url).pathname)) return;
|
||||
Object.defineProperty(event.request, "waitUntil", { value: event.waitUntil.bind(event) });
|
||||
const response = await this.fetch(event.request, event);
|
||||
if (response.status !== 404) event.respondWith(response);
|
||||
};
|
||||
addEventListener("fetch", this.#fetchListener);
|
||||
self.addEventListener("install", () => {
|
||||
self.skipWaiting();
|
||||
});
|
||||
self.addEventListener("activate", () => {
|
||||
self.clients?.claim?.();
|
||||
});
|
||||
}
|
||||
}
|
||||
ready() {
|
||||
return Promise.resolve(this.#listeningPromise).then(() => this);
|
||||
}
|
||||
async close() {
|
||||
if (this.#fetchListener) removeEventListener("fetch", this.#fetchListener);
|
||||
if (isBrowserWindow) {
|
||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
||||
for (const registration of registrations) if (registration.active) await registration.unregister();
|
||||
} else if (isServiceWorker) await self.registration.unregister();
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { FastResponse, FastURL, serve };
|
||||
17
node_modules/srvx/dist/cli.d.mts
generated
vendored
Normal file
17
node_modules/srvx/dist/cli.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { Server } from "srvx";
|
||||
|
||||
//#region src/cli.d.ts
|
||||
declare function main(mainOpts: MainOpts): Promise<void>;
|
||||
declare global {
|
||||
var __srvx_version__: string | undefined;
|
||||
var __srvx__: Server;
|
||||
var __srvx_listen_cb__: () => void;
|
||||
}
|
||||
type MainOpts = {
|
||||
command: string;
|
||||
docs: string;
|
||||
issues: string;
|
||||
};
|
||||
declare function usage(mainOpts: MainOpts): string;
|
||||
//#endregion
|
||||
export { main, usage };
|
||||
352
node_modules/srvx/dist/cli.mjs
generated
vendored
Normal file
352
node_modules/srvx/dist/cli.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
import { Colors } from "./_chunks/_utils.cli-B2YzwlOv.mjs";
|
||||
import { parseArgs } from "node:util";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { dirname, extname, relative, resolve } from "node:path";
|
||||
import { fork } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
|
||||
//#region src/cli.ts
|
||||
const defaultEntries = [
|
||||
"server",
|
||||
"index",
|
||||
"src/server",
|
||||
"src/index",
|
||||
"server/index"
|
||||
];
|
||||
const defaultExts = [
|
||||
".mts",
|
||||
".ts",
|
||||
".cts",
|
||||
".js",
|
||||
".mjs",
|
||||
".cjs",
|
||||
".jsx",
|
||||
".tsx"
|
||||
];
|
||||
const args = process.argv.slice(2);
|
||||
const options = parseArgs$1(args);
|
||||
if (process.send) {
|
||||
setupProcessErrorHandlers();
|
||||
await serve();
|
||||
}
|
||||
async function main(mainOpts) {
|
||||
setupProcessErrorHandlers();
|
||||
if (options._version) {
|
||||
console.log(await version());
|
||||
process.exit(0);
|
||||
}
|
||||
if (options._help) {
|
||||
console.log(usage(mainOpts));
|
||||
process.exit(options._help ? 0 : 1);
|
||||
}
|
||||
const isBun = !!process.versions.bun;
|
||||
const isDeno = !!process.versions.deno;
|
||||
const isNode = !isBun && !isDeno;
|
||||
const runtimeArgs = [];
|
||||
if (!options._prod) runtimeArgs.push("--watch");
|
||||
if (isNode || isDeno) runtimeArgs.push(...[".env", options._prod ? ".env.production" : ".env.local"].filter((f) => existsSync(f)).map((f) => `--env-file=${f}`));
|
||||
if (isNode) {
|
||||
const [major, minor] = process.versions.node.split(".");
|
||||
if (major === "22" && +minor >= 6) runtimeArgs.push("--experimental-strip-types");
|
||||
if (options._import) runtimeArgs.push(`--import=${options._import}`);
|
||||
}
|
||||
const child = fork(fileURLToPath(import.meta.url), args, { execArgv: [...process.execArgv, ...runtimeArgs].filter(Boolean) });
|
||||
child.on("error", (error) => {
|
||||
console.error("Error in child process:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
child.on("exit", (code) => {
|
||||
if (code !== 0) {
|
||||
console.error(`Child process exited with code ${code}`);
|
||||
process.exit(code);
|
||||
}
|
||||
});
|
||||
}
|
||||
async function serve() {
|
||||
try {
|
||||
if (!process.env.NODE_ENV) process.env.NODE_ENV = options._prod ? "production" : "development";
|
||||
const entry = await loadEntry(options);
|
||||
const forceUseNode = entry._legacyNode;
|
||||
const { serve: srvxServe } = forceUseNode ? await import("srvx/node") : await import("srvx");
|
||||
const { serveStatic } = await import("srvx/static");
|
||||
const { log } = await import("srvx/log");
|
||||
const staticDir = resolve(options._dir, options._static);
|
||||
options._static = existsSync(staticDir) ? staticDir : "";
|
||||
const server = srvxServe({
|
||||
error: (error) => {
|
||||
console.error(error);
|
||||
return renderError(error);
|
||||
},
|
||||
middleware: [
|
||||
log(),
|
||||
options._static ? serveStatic({ dir: options._static }) : void 0,
|
||||
...entry.middleware || []
|
||||
].filter(Boolean),
|
||||
...entry
|
||||
});
|
||||
globalThis.__srvx__ = server;
|
||||
await server.ready();
|
||||
await globalThis.__srvx_listen_cb__?.();
|
||||
printInfo(entry);
|
||||
const cleanup = () => {
|
||||
server.close(true).catch(() => {});
|
||||
process.exit(0);
|
||||
};
|
||||
process.on("SIGINT", () => {
|
||||
console.log(Colors.gray("\rStopping server..."));
|
||||
cleanup();
|
||||
});
|
||||
process.on("SIGTERM", cleanup);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
async function loadEntry(opts) {
|
||||
try {
|
||||
if (!opts._entry) for (const entry of defaultEntries) {
|
||||
for (const ext of defaultExts) {
|
||||
const entryPath = resolve(opts._dir, `${entry}${ext}`);
|
||||
if (existsSync(entryPath)) {
|
||||
opts._entry = entryPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opts._entry) break;
|
||||
}
|
||||
if (!opts._entry) {
|
||||
const _error$1 = `No server entry file found.\nPlease specify an entry file or ensure one of the default entries exists (${defaultEntries.join(", ")}).`;
|
||||
return {
|
||||
_error: _error$1,
|
||||
fetch: () => renderError(_error$1, 404, "No Server Entry"),
|
||||
...opts
|
||||
};
|
||||
}
|
||||
const entryURL = opts._entry.startsWith("file://") ? opts._entry : pathToFileURL(resolve(opts._entry)).href;
|
||||
const { res: mod, listenHandler } = await interceptListen(() => import(entryURL));
|
||||
let fetchHandler = mod.fetch || mod.default?.fetch || mod.default?.default?.fetch;
|
||||
let _legacyNode = false;
|
||||
if (!fetchHandler) {
|
||||
const nodeHandler = listenHandler || (typeof mod.default === "function" ? mod.default : void 0);
|
||||
if (nodeHandler) {
|
||||
_legacyNode = true;
|
||||
const { callNodeHandler } = await import("./_chunks/call-LB9MY5Dv.mjs");
|
||||
fetchHandler = (webReq) => callNodeHandler(nodeHandler, webReq);
|
||||
}
|
||||
}
|
||||
let _error;
|
||||
if (!fetchHandler) {
|
||||
_error = `The entry file "${relative(".", opts._entry)}" does not export a valid fetch handler.`;
|
||||
fetchHandler = () => renderError(_error, 500, "Invalid Entry");
|
||||
}
|
||||
return {
|
||||
...mod,
|
||||
...mod.default,
|
||||
...opts,
|
||||
_error,
|
||||
_legacyNode,
|
||||
fetch: fetchHandler
|
||||
};
|
||||
} catch (error) {
|
||||
if (error?.code === "ERR_UNKNOWN_FILE_EXTENSION") {
|
||||
const message = String(error);
|
||||
if (/"\.(m|c)?ts"/g.test(message)) console.error(Colors.red(`\nMake sure you're using Node.js v22.18+ or v24+ for TypeScript support (current version: ${process.versions.node})\n\n`));
|
||||
else if (/"\.(m|c)?tsx"/g.test(message)) console.error(Colors.red(`\nYou need a compatible loader for JSX support (Deno, Bun or srvx --register jiti/register)\n\n`));
|
||||
}
|
||||
if (error instanceof Error) Error.captureStackTrace?.(error, serve);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
function renderError(error, status = 500, title = "Server Error") {
|
||||
let html = `<!DOCTYPE html><html><head><title>${title}</title></head><body>`;
|
||||
if (options._prod) html += `<h1>${title}</h1><p>Something went wrong while processing your request.</p>`;
|
||||
else html += `
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background: #f8f9fa; color: #333; }
|
||||
h1 { color: #dc3545; }
|
||||
pre { background: #fff; padding: 10px; border-radius: 5px; overflow: auto; }
|
||||
code { font-family: monospace; }
|
||||
#error { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; }
|
||||
</style>
|
||||
<div id="error"><h1>${title}</h1><pre>${error instanceof Error ? error.stack || error.message : String(error)}</pre></div>
|
||||
`;
|
||||
return new Response(html, {
|
||||
status,
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" }
|
||||
});
|
||||
}
|
||||
function printInfo(entry) {
|
||||
let entryInfo;
|
||||
if (options._entry) entryInfo = Colors.cyan("./" + relative(".", options._entry));
|
||||
else entryInfo = Colors.gray(`(create ${Colors.bold(`server.ts`)} to enable)`);
|
||||
console.log(Colors.gray(`${Colors.bold(Colors.gray("λ"))} Server handler: ${entryInfo}`));
|
||||
if (options._entry && entry._error) console.error(Colors.red(` ${entry._error}`));
|
||||
let staticInfo;
|
||||
if (options._static) staticInfo = Colors.cyan("./" + relative(".", options._static) + "/");
|
||||
else staticInfo = Colors.gray(`(add ${Colors.bold("public/")} dir to enable)`);
|
||||
console.log(Colors.gray(`${Colors.bold(Colors.gray("∘"))} Static files: ${staticInfo}`));
|
||||
}
|
||||
async function interceptListen(cb) {
|
||||
const http = process.getBuiltinModule("node:http");
|
||||
if (!http || !http.Server) {
|
||||
const res$1 = await cb();
|
||||
return { res: res$1 };
|
||||
}
|
||||
const originalListen = http.Server.prototype.listen;
|
||||
let res;
|
||||
let listenHandler;
|
||||
try {
|
||||
http.Server.prototype.listen = function(arg1, arg2) {
|
||||
listenHandler = this._events.request;
|
||||
if (Array.isArray(listenHandler)) listenHandler = listenHandler[0];
|
||||
http.Server.prototype.listen = originalListen;
|
||||
globalThis.__srvx_listen_cb__ = [arg1, arg2].find((arg) => typeof arg === "function");
|
||||
return new Proxy({}, { get(_, prop) {
|
||||
const server = globalThis.__srvx__;
|
||||
return server?.node?.server?.[prop];
|
||||
} });
|
||||
};
|
||||
res = await cb();
|
||||
} finally {
|
||||
http.Server.prototype.listen = originalListen;
|
||||
}
|
||||
return {
|
||||
res,
|
||||
listenHandler
|
||||
};
|
||||
}
|
||||
async function version() {
|
||||
const version$1 = "0.8.9";
|
||||
return `srvx ${version$1}\n${runtime()}`;
|
||||
}
|
||||
function runtime() {
|
||||
if (process.versions.bun) return `bun ${process.versions.bun}`;
|
||||
else if (process.versions.deno) return `deno ${process.versions.deno}`;
|
||||
else return `node ${process.versions.node}`;
|
||||
}
|
||||
function parseArgs$1(args$1) {
|
||||
const { values, positionals } = parseArgs({
|
||||
args: args$1,
|
||||
allowPositionals: true,
|
||||
options: {
|
||||
help: {
|
||||
type: "boolean",
|
||||
short: "h"
|
||||
},
|
||||
version: {
|
||||
type: "boolean",
|
||||
short: "v"
|
||||
},
|
||||
prod: { type: "boolean" },
|
||||
port: {
|
||||
type: "string",
|
||||
short: "p"
|
||||
},
|
||||
host: {
|
||||
type: "string",
|
||||
short: "H"
|
||||
},
|
||||
static: {
|
||||
type: "string",
|
||||
short: "s"
|
||||
},
|
||||
import: { type: "string" },
|
||||
tls: { type: "boolean" },
|
||||
cert: { type: "string" },
|
||||
key: { type: "string" }
|
||||
}
|
||||
});
|
||||
const input = positionals[0] || ".";
|
||||
let dir;
|
||||
let entry = "";
|
||||
if (extname(input) === "") dir = resolve(input);
|
||||
else {
|
||||
entry = resolve(input);
|
||||
dir = dirname(entry);
|
||||
}
|
||||
if (!existsSync(dir)) {
|
||||
console.error(Colors.red(`Directory "${dir}" does not exist.\n`));
|
||||
process.exit(1);
|
||||
}
|
||||
return {
|
||||
_dir: dir,
|
||||
_entry: entry,
|
||||
_prod: values.prod ?? process.env.NODE_ENV === "production",
|
||||
_help: values.help,
|
||||
_static: values.static || "public",
|
||||
_version: values.version,
|
||||
_import: values.import,
|
||||
port: values.port ? Number.parseInt(values.port, 10) : void 0,
|
||||
hostname: values.host,
|
||||
tls: values.tls ? {
|
||||
cert: values.cert,
|
||||
key: values.key
|
||||
} : void 0
|
||||
};
|
||||
}
|
||||
function example() {
|
||||
const useTs = !options._entry || options._entry.endsWith(".ts");
|
||||
return `${Colors.bold(Colors.gray("// server.ts"))}
|
||||
${Colors.magenta("export default")} {
|
||||
${Colors.cyan("fetch")}(req${useTs ? ": Request" : ""}) {
|
||||
${Colors.magenta("return")} new Response(${Colors.green("\"Hello, World!\"")});
|
||||
}
|
||||
}`;
|
||||
}
|
||||
function usage(mainOpts) {
|
||||
const command = mainOpts.command;
|
||||
return `
|
||||
${Colors.cyan(command)} - Start an HTTP server with the specified entry path.
|
||||
|
||||
${Colors.bold("USAGE")}
|
||||
${existsSync(options._entry) ? "" : `\n${example()}\n`}
|
||||
${Colors.gray("# srvx [options] [entry]")}
|
||||
${Colors.gray("$")} ${Colors.cyan(command)} ${Colors.gray("./server.ts")} ${Colors.gray("# Start development server")}
|
||||
${Colors.gray("$")} ${Colors.cyan(command)} --prod ${Colors.gray("# Start production server")}
|
||||
${Colors.gray("$")} ${Colors.cyan(command)} --port=8080 ${Colors.gray("# Listen on port 8080")}
|
||||
${Colors.gray("$")} ${Colors.cyan(command)} --host=localhost ${Colors.gray("# Bind to localhost only")}
|
||||
${Colors.gray("$")} ${Colors.cyan(command)} --import=jiti/register ${Colors.gray(`# Enable ${Colors.url("jiti", "https://github.com/unjs/jiti")} loader`)}
|
||||
${Colors.gray("$")} ${Colors.cyan(command)} --tls --cert=cert.pem --key=key.pem ${Colors.gray("# Enable TLS (HTTPS/HTTP2)")}
|
||||
|
||||
|
||||
${Colors.bold("ARGUMENTS")}
|
||||
|
||||
${Colors.yellow("<entry>")} Server entry path to serve.
|
||||
Default: ${defaultEntries.map((e) => Colors.cyan(e)).join(", ")} ${Colors.gray(`(${defaultExts.join(",")})`)}
|
||||
|
||||
${Colors.bold("OPTIONS")}
|
||||
|
||||
${Colors.green("-p, --port")} ${Colors.yellow("<port>")} Port to listen on (default: ${Colors.yellow("3000")})
|
||||
${Colors.green("--host")} ${Colors.yellow("<host>")} Host to bind to (default: all interfaces)
|
||||
${Colors.green("-s, --static")} ${Colors.yellow("<dir>")} Serve static files from the specified directory (default: ${Colors.yellow("public")})
|
||||
${Colors.green("--prod")} Run in production mode (no watch, no debug)
|
||||
${Colors.green("--import")} ${Colors.yellow("<loader>")} ES module to preload
|
||||
${Colors.green("--tls")} Enable TLS (HTTPS/HTTP2)
|
||||
${Colors.green("--cert")} ${Colors.yellow("<file>")} TLS certificate file
|
||||
${Colors.green("--key")} ${Colors.yellow("<file>")} TLS private key file
|
||||
${Colors.green("-h, --help")} Show this help message
|
||||
${Colors.green("-v, --version")} Show server and runtime versions
|
||||
|
||||
${Colors.bold("ENVIRONMENT")}
|
||||
|
||||
${Colors.green("PORT")} Override port
|
||||
${Colors.green("HOST")} Override host
|
||||
${Colors.green("NODE_ENV")} Set to ${Colors.yellow("production")} for production mode.
|
||||
|
||||
➤ ${Colors.url("Documentation", mainOpts.docs || "https://srvx.h3.dev")}
|
||||
➤ ${Colors.url("Report issues", mainOpts.issues || "https://github.com/h3js/srvx/issues")}
|
||||
`.trim();
|
||||
}
|
||||
function setupProcessErrorHandlers() {
|
||||
process.on("uncaughtException", (error) => {
|
||||
console.error("Uncaught exception:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
process.on("unhandledRejection", (reason) => {
|
||||
console.error("Unhandled rejection:", reason);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
//#endregion
|
||||
export { main, usage };
|
||||
8
node_modules/srvx/dist/log.d.mts
generated
vendored
Normal file
8
node_modules/srvx/dist/log.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { ServerMiddleware } from "./_chunks/types-BtByT9ny.mjs";
|
||||
|
||||
//#region src/log.d.ts
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
interface LogOptions {}
|
||||
declare const log: (_options?: LogOptions) => ServerMiddleware;
|
||||
//#endregion
|
||||
export { LogOptions, log };
|
||||
21
node_modules/srvx/dist/log.mjs
generated
vendored
Normal file
21
node_modules/srvx/dist/log.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { Colors } from "./_chunks/_utils.cli-B2YzwlOv.mjs";
|
||||
|
||||
//#region src/log.ts
|
||||
const statusColors = {
|
||||
1: "blue",
|
||||
2: "green",
|
||||
3: "yellow"
|
||||
};
|
||||
const log = (_options = {}) => {
|
||||
return async (req, next) => {
|
||||
const start = performance.now();
|
||||
const res = await next();
|
||||
const duration = performance.now() - start;
|
||||
const statusColor = statusColors[Math.floor(res.status / 100)] || "red";
|
||||
console.log(`${Colors.gray(`[${new Date().toLocaleTimeString()}]`)} ${Colors.bold(req.method)} ${Colors.blue(req.url)} [${Colors[statusColor](res.status + "")}] ${Colors.gray(`(${duration.toFixed(2)}ms)`)}`);
|
||||
return res;
|
||||
};
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { log };
|
||||
9
node_modules/srvx/dist/static.d.mts
generated
vendored
Normal file
9
node_modules/srvx/dist/static.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { ServerMiddleware } from "./_chunks/types-BtByT9ny.mjs";
|
||||
|
||||
//#region src/static.d.ts
|
||||
interface ServeStaticOptions {
|
||||
dir: string;
|
||||
}
|
||||
declare const serveStatic: (options: ServeStaticOptions) => ServerMiddleware;
|
||||
//#endregion
|
||||
export { ServeStaticOptions, serveStatic };
|
||||
70
node_modules/srvx/dist/static.mjs
generated
vendored
Normal file
70
node_modules/srvx/dist/static.mjs
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { extname, join, resolve } from "node:path";
|
||||
import { createReadStream } from "node:fs";
|
||||
import { stat } from "node:fs/promises";
|
||||
import { FastResponse } from "srvx";
|
||||
import { createBrotliCompress, createGzip } from "node:zlib";
|
||||
|
||||
//#region src/static.ts
|
||||
const COMMON_MIME_TYPES = {
|
||||
".html": "text/html",
|
||||
".htm": "text/html",
|
||||
".css": "text/css",
|
||||
".js": "text/javascript",
|
||||
".mjs": "text/javascript",
|
||||
".json": "application/json",
|
||||
".txt": "text/plain",
|
||||
".xml": "application/xml",
|
||||
".gif": "image/gif",
|
||||
".ico": "image/vnd.microsoft.icon",
|
||||
".jpeg": "image/jpeg",
|
||||
".jpg": "image/jpeg",
|
||||
".png": "image/png",
|
||||
".svg": "image/svg+xml",
|
||||
".webp": "image/webp",
|
||||
".woff": "font/woff",
|
||||
".woff2": "font/woff2",
|
||||
".mp4": "video/mp4",
|
||||
".webm": "video/webm",
|
||||
".zip": "application/zip",
|
||||
".pdf": "application/pdf"
|
||||
};
|
||||
const serveStatic = (options) => {
|
||||
const dir = resolve(options.dir) + "/";
|
||||
return async (req, next) => {
|
||||
if (req.method !== "GET" && req.method !== "HEAD") return next();
|
||||
const path = new URL(req.url).pathname.slice(1).replace(/\/$/, "");
|
||||
let paths;
|
||||
if (path === "") paths = ["index.html"];
|
||||
else if (extname(path) === "") paths = [`${path}.html`, `${path}/index.html`];
|
||||
else paths = [path];
|
||||
for (const path$1 of paths) {
|
||||
const filePath = join(dir, path$1);
|
||||
if (!filePath.startsWith(dir)) continue;
|
||||
const fileStat = await stat(filePath).catch(() => null);
|
||||
if (fileStat?.isFile()) {
|
||||
const headers = {
|
||||
"Content-Length": fileStat.size.toString(),
|
||||
"Content-Type": COMMON_MIME_TYPES[extname(filePath)] || "application/octet-stream"
|
||||
};
|
||||
let stream = createReadStream(filePath);
|
||||
const acceptEncoding = req.headers.get("accept-encoding") || "";
|
||||
if (acceptEncoding.includes("br")) {
|
||||
headers["Content-Encoding"] = "br";
|
||||
delete headers["Content-Length"];
|
||||
headers["Vary"] = "Accept-Encoding";
|
||||
stream = stream.pipe(createBrotliCompress());
|
||||
} else if (acceptEncoding.includes("gzip")) {
|
||||
headers["Content-Encoding"] = "gzip";
|
||||
delete headers["Content-Length"];
|
||||
headers["Vary"] = "Accept-Encoding";
|
||||
stream = stream.pipe(createGzip());
|
||||
}
|
||||
return new FastResponse(stream, { headers });
|
||||
}
|
||||
}
|
||||
return next();
|
||||
};
|
||||
};
|
||||
|
||||
//#endregion
|
||||
export { serveStatic };
|
||||
2
node_modules/srvx/dist/types.d.mts
generated
vendored
Normal file
2
node_modules/srvx/dist/types.d.mts
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTPMiddleware, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, serve } from "./_chunks/types-BtByT9ny.mjs";
|
||||
export { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTPMiddleware, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, serve };
|
||||
Loading…
Add table
Add a link
Reference in a new issue