srvx 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/bun.d.mts +3 -2
- package/dist/adapters/bun.mjs +8 -6
- package/dist/adapters/cloudflare.d.mts +3 -2
- package/dist/adapters/cloudflare.mjs +10 -8
- package/dist/adapters/deno.d.mts +3 -2
- package/dist/adapters/deno.mjs +8 -6
- package/dist/adapters/generic.d.mts +3 -2
- package/dist/adapters/generic.mjs +6 -8
- package/dist/adapters/node.d.mts +12 -6
- package/dist/adapters/node.mjs +48 -10
- package/dist/adapters/service-worker.d.mts +3 -2
- package/dist/adapters/service-worker.mjs +6 -8
- package/dist/shared/srvx.BMykKwGg.mjs +16 -0
- package/dist/shared/srvx.CEIXM-sv.mjs +18 -0
- package/dist/shared/srvx.Ctaz0clH.mjs +172 -0
- package/dist/shared/srvx.DEE2RO4O.d.mts +5 -0
- package/dist/shared/srvx.zEohKxBQ.mjs +20 -0
- package/dist/types.d.mts +22 -22
- package/package.json +8 -3
- package/dist/shared/srvx.BD9sRkkl.mjs +0 -16
- package/dist/shared/srvx.DhN4g5wJ.mjs +0 -76
- package/dist/shared/srvx.FQfHxe2J.mjs +0 -75
package/dist/adapters/bun.d.mts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ServerOptions, Server, BunFetchHandler } from '../types.mjs';
|
|
2
2
|
import * as Bun from 'bun';
|
|
3
|
+
export { F as FastURL } from '../shared/srvx.DEE2RO4O.mjs';
|
|
3
4
|
import 'node:http';
|
|
4
5
|
import 'node:https';
|
|
5
6
|
import 'node:net';
|
|
6
7
|
import '@cloudflare/workers-types';
|
|
7
8
|
|
|
8
|
-
declare const
|
|
9
|
+
declare const FastResponse: typeof globalThis.Response;
|
|
9
10
|
declare function serve(options: ServerOptions): BunServer;
|
|
10
11
|
declare class BunServer implements Server<BunFetchHandler> {
|
|
11
12
|
readonly runtime = "bun";
|
|
@@ -20,4 +21,4 @@ declare class BunServer implements Server<BunFetchHandler> {
|
|
|
20
21
|
close(closeAll?: boolean): Promise<void>;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
export {
|
|
24
|
+
export { FastResponse, serve };
|
package/dist/adapters/bun.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { r as resolveTLSOptions, a as resolvePortAndHost, p as printListening, f as fmtURL } from '../shared/srvx.
|
|
2
|
-
|
|
1
|
+
import { r as resolveTLSOptions, a as resolvePortAndHost, p as printListening, f as fmtURL } from '../shared/srvx.Ctaz0clH.mjs';
|
|
2
|
+
export { F as FastURL } from '../shared/srvx.Ctaz0clH.mjs';
|
|
3
|
+
import { w as wrapFetch } from '../shared/srvx.zEohKxBQ.mjs';
|
|
4
|
+
import { w as wsUpgradePlugin } from '../shared/srvx.BMykKwGg.mjs';
|
|
3
5
|
import 'node:fs';
|
|
4
6
|
|
|
5
|
-
const
|
|
7
|
+
const FastResponse = Response;
|
|
6
8
|
function serve(options) {
|
|
7
9
|
return new BunServer(options);
|
|
8
10
|
}
|
|
@@ -11,7 +13,7 @@ class BunServer {
|
|
|
11
13
|
this.runtime = "bun";
|
|
12
14
|
this.bun = {};
|
|
13
15
|
this.options = options;
|
|
14
|
-
const fetchHandler = wrapFetch(this,
|
|
16
|
+
const fetchHandler = wrapFetch(this, [wsUpgradePlugin]);
|
|
15
17
|
this.fetch = (request, server) => {
|
|
16
18
|
Object.defineProperties(request, {
|
|
17
19
|
runtime: {
|
|
@@ -31,7 +33,7 @@ class BunServer {
|
|
|
31
33
|
this.serveOptions = {
|
|
32
34
|
...resolvePortAndHost(this.options),
|
|
33
35
|
reusePort: this.options.reusePort,
|
|
34
|
-
error: this.options.
|
|
36
|
+
error: this.options.error,
|
|
35
37
|
...this.options.bun,
|
|
36
38
|
tls: {
|
|
37
39
|
cert: tls?.cert,
|
|
@@ -75,4 +77,4 @@ class BunServer {
|
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
export {
|
|
80
|
+
export { FastResponse, serve };
|
|
@@ -5,7 +5,8 @@ import 'node:https';
|
|
|
5
5
|
import 'node:net';
|
|
6
6
|
import 'bun';
|
|
7
7
|
|
|
8
|
-
declare const
|
|
8
|
+
declare const FastURL: typeof globalThis.URL;
|
|
9
|
+
declare const FastResponse: typeof globalThis.Response;
|
|
9
10
|
declare function serve(options: ServerOptions): Server<CF.ExportedHandlerFetchHandler>;
|
|
10
11
|
|
|
11
|
-
export {
|
|
12
|
+
export { FastResponse, FastURL, serve };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { w as wrapFetch } from '../shared/srvx.
|
|
2
|
-
import {
|
|
1
|
+
import { w as wrapFetch } from '../shared/srvx.zEohKxBQ.mjs';
|
|
2
|
+
import { e as errorPlugin } from '../shared/srvx.CEIXM-sv.mjs';
|
|
3
|
+
import { w as wsUpgradePlugin } from '../shared/srvx.BMykKwGg.mjs';
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
+
const FastURL = URL;
|
|
6
|
+
const FastResponse = Response;
|
|
5
7
|
function serve(options) {
|
|
6
8
|
return new CloudflareServer(options);
|
|
7
9
|
}
|
|
@@ -9,10 +11,10 @@ class CloudflareServer {
|
|
|
9
11
|
constructor(options) {
|
|
10
12
|
this.runtime = "cloudflare";
|
|
11
13
|
this.options = options;
|
|
12
|
-
const fetchHandler = wrapFetch(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
);
|
|
14
|
+
const fetchHandler = wrapFetch(this, [
|
|
15
|
+
errorPlugin,
|
|
16
|
+
wsUpgradePlugin
|
|
17
|
+
]);
|
|
16
18
|
this.fetch = (request, env, context) => {
|
|
17
19
|
Object.defineProperties(request, {
|
|
18
20
|
runtime: {
|
|
@@ -49,4 +51,4 @@ class CloudflareServer {
|
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
export {
|
|
54
|
+
export { FastResponse, FastURL, serve };
|
package/dist/adapters/deno.d.mts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ServerOptions, Server, DenoFetchHandler } from '../types.mjs';
|
|
2
|
+
export { F as FastURL } from '../shared/srvx.DEE2RO4O.mjs';
|
|
2
3
|
import 'node:http';
|
|
3
4
|
import 'node:https';
|
|
4
5
|
import 'node:net';
|
|
5
6
|
import 'bun';
|
|
6
7
|
import '@cloudflare/workers-types';
|
|
7
8
|
|
|
8
|
-
declare const
|
|
9
|
+
declare const FastResponse: typeof globalThis.Response;
|
|
9
10
|
declare function serve(options: ServerOptions): DenoServer;
|
|
10
11
|
declare class DenoServer implements Server<DenoFetchHandler> {
|
|
11
12
|
#private;
|
|
@@ -21,4 +22,4 @@ declare class DenoServer implements Server<DenoFetchHandler> {
|
|
|
21
22
|
close(): Promise<void | undefined>;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
export {
|
|
25
|
+
export { FastResponse, serve };
|
package/dist/adapters/deno.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { r as resolveTLSOptions, a as resolvePortAndHost, p as printListening, f as fmtURL } from '../shared/srvx.
|
|
2
|
-
|
|
1
|
+
import { r as resolveTLSOptions, a as resolvePortAndHost, p as printListening, f as fmtURL } from '../shared/srvx.Ctaz0clH.mjs';
|
|
2
|
+
export { F as FastURL } from '../shared/srvx.Ctaz0clH.mjs';
|
|
3
|
+
import { w as wrapFetch } from '../shared/srvx.zEohKxBQ.mjs';
|
|
4
|
+
import { w as wsUpgradePlugin } from '../shared/srvx.BMykKwGg.mjs';
|
|
3
5
|
import 'node:fs';
|
|
4
6
|
|
|
5
|
-
const
|
|
7
|
+
const FastResponse = Response;
|
|
6
8
|
function serve(options) {
|
|
7
9
|
return new DenoServer(options);
|
|
8
10
|
}
|
|
@@ -11,7 +13,7 @@ class DenoServer {
|
|
|
11
13
|
this.runtime = "deno";
|
|
12
14
|
this.deno = {};
|
|
13
15
|
this.options = options;
|
|
14
|
-
const fetchHandler = wrapFetch(this,
|
|
16
|
+
const fetchHandler = wrapFetch(this, [wsUpgradePlugin]);
|
|
15
17
|
this.fetch = (request, info) => {
|
|
16
18
|
Object.defineProperties(request, {
|
|
17
19
|
runtime: {
|
|
@@ -31,7 +33,7 @@ class DenoServer {
|
|
|
31
33
|
this.serveOptions = {
|
|
32
34
|
...resolvePortAndHost(this.options),
|
|
33
35
|
reusePort: this.options.reusePort,
|
|
34
|
-
onError: this.options.
|
|
36
|
+
onError: this.options.error,
|
|
35
37
|
...tls ? { key: tls.key, cert: tls.cert, passphrase: tls.passphrase } : {},
|
|
36
38
|
...this.options.deno
|
|
37
39
|
};
|
|
@@ -78,4 +80,4 @@ class DenoServer {
|
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
export {
|
|
83
|
+
export { FastResponse, serve };
|
|
@@ -5,7 +5,8 @@ import 'node:net';
|
|
|
5
5
|
import 'bun';
|
|
6
6
|
import '@cloudflare/workers-types';
|
|
7
7
|
|
|
8
|
-
declare const
|
|
8
|
+
declare const FastURL: typeof globalThis.URL;
|
|
9
|
+
declare const FastResponse: typeof globalThis.Response;
|
|
9
10
|
declare function serve(options: ServerOptions): Server;
|
|
10
11
|
|
|
11
|
-
export {
|
|
12
|
+
export { FastResponse, FastURL, serve };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { w as wrapFetch } from '../shared/srvx.
|
|
2
|
-
import {
|
|
1
|
+
import { w as wrapFetch } from '../shared/srvx.zEohKxBQ.mjs';
|
|
2
|
+
import { e as errorPlugin } from '../shared/srvx.CEIXM-sv.mjs';
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const FastURL = URL;
|
|
5
|
+
const FastResponse = Response;
|
|
5
6
|
function serve(options) {
|
|
6
7
|
return new GenericServer(options);
|
|
7
8
|
}
|
|
@@ -9,10 +10,7 @@ class GenericServer {
|
|
|
9
10
|
constructor(options) {
|
|
10
11
|
this.runtime = "generic";
|
|
11
12
|
this.options = options;
|
|
12
|
-
const fetchHandler = wrapFetch(
|
|
13
|
-
this,
|
|
14
|
-
wrapFetchOnError(this.options.fetch, this.options.onError)
|
|
15
|
-
);
|
|
13
|
+
const fetchHandler = wrapFetch(this, [errorPlugin]);
|
|
16
14
|
this.fetch = (request) => {
|
|
17
15
|
return Promise.resolve(fetchHandler(request));
|
|
18
16
|
};
|
|
@@ -27,4 +25,4 @@ class GenericServer {
|
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
export {
|
|
28
|
+
export { FastResponse, FastURL, serve };
|
package/dist/adapters/node.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ServerRequest, ServerOptions, Server, FetchHandler, NodeHttpHandler } from '../types.mjs';
|
|
2
|
+
export { F as FastURL } from '../shared/srvx.DEE2RO4O.mjs';
|
|
2
3
|
import NodeHttp__default from 'node:http';
|
|
3
|
-
import { Readable } from 'node:stream';
|
|
4
|
+
import NodeStream, { Readable } from 'node:stream';
|
|
4
5
|
import 'node:https';
|
|
5
6
|
import 'node:net';
|
|
6
7
|
import 'bun';
|
|
@@ -23,11 +24,16 @@ declare const NodeResponse: {
|
|
|
23
24
|
};
|
|
24
25
|
};
|
|
25
26
|
|
|
27
|
+
type NodeRequestContext = {
|
|
28
|
+
req: NodeHttp__default.IncomingMessage;
|
|
29
|
+
res?: NodeHttp__default.ServerResponse;
|
|
30
|
+
upgrade?: {
|
|
31
|
+
socket: NodeStream.Duplex;
|
|
32
|
+
header: Buffer;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
26
35
|
declare const NodeRequest: {
|
|
27
|
-
new (nodeCtx:
|
|
28
|
-
req: NodeHttp__default.IncomingMessage;
|
|
29
|
-
res: NodeHttp__default.ServerResponse;
|
|
30
|
-
}): ServerRequest;
|
|
36
|
+
new (nodeCtx: NodeRequestContext): ServerRequest;
|
|
31
37
|
};
|
|
32
38
|
|
|
33
39
|
declare const NodeRequestHeaders: {
|
|
@@ -46,4 +52,4 @@ declare const NodeResponseHeaders: {
|
|
|
46
52
|
declare function serve(options: ServerOptions): Server;
|
|
47
53
|
declare function toNodeHandler(fetchHandler: FetchHandler): NodeHttpHandler;
|
|
48
54
|
|
|
49
|
-
export { NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders,
|
|
55
|
+
export { NodeResponse as FastResponse, NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, serve, toNodeHandler };
|
package/dist/adapters/node.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import NodeHttp from 'node:http';
|
|
2
2
|
import NodeHttps from 'node:https';
|
|
3
3
|
import { splitSetCookieString } from 'cookie-es';
|
|
4
|
-
import { r as resolveTLSOptions, a as resolvePortAndHost, p as printListening, f as fmtURL } from '../shared/srvx.
|
|
5
|
-
|
|
6
|
-
import { w as
|
|
4
|
+
import { r as resolveTLSOptions, a as resolvePortAndHost, p as printListening, f as fmtURL } from '../shared/srvx.Ctaz0clH.mjs';
|
|
5
|
+
export { F as FastURL } from '../shared/srvx.Ctaz0clH.mjs';
|
|
6
|
+
import { w as wrapFetch } from '../shared/srvx.zEohKxBQ.mjs';
|
|
7
|
+
import { e as errorPlugin } from '../shared/srvx.CEIXM-sv.mjs';
|
|
7
8
|
import 'node:fs';
|
|
8
9
|
|
|
9
10
|
async function sendNodeResponse(nodeRes, webRes) {
|
|
@@ -46,6 +47,23 @@ async function sendNodeResponse(nodeRes, webRes) {
|
|
|
46
47
|
}
|
|
47
48
|
return webRes.body ? streamBody(webRes.body, nodeRes) : endNodeResponse(nodeRes);
|
|
48
49
|
}
|
|
50
|
+
async function sendNodeUpgradeResponse(socket, res) {
|
|
51
|
+
const head = [
|
|
52
|
+
`HTTP/1.1 ${res.status || 200} ${res.statusText || ""}`,
|
|
53
|
+
...[...res.headers.entries()].map(
|
|
54
|
+
([key, value]) => `${encodeURIComponent(key)}: ${encodeURIComponent(value)}`
|
|
55
|
+
)
|
|
56
|
+
];
|
|
57
|
+
socket.write(head.join("\r\n") + "\r\n\r\n");
|
|
58
|
+
if (res.body) {
|
|
59
|
+
for await (const chunk of res.body) {
|
|
60
|
+
socket.write(chunk);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
socket.end(resolve);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
49
67
|
function endNodeResponse(nodeRes) {
|
|
50
68
|
return new Promise((resolve) => nodeRes.end(resolve));
|
|
51
69
|
}
|
|
@@ -688,7 +706,7 @@ const NodeResponse = /* @__PURE__ */ (() => {
|
|
|
688
706
|
const headers = [];
|
|
689
707
|
const headersInit = this.#init?.headers;
|
|
690
708
|
if (headersInit) {
|
|
691
|
-
const headerEntries = headersInit.entries ? headersInit.entries() : Object.entries(headersInit);
|
|
709
|
+
const headerEntries = Array.isArray(headersInit) ? headersInit : headersInit.entries ? headersInit.entries() : Object.entries(headersInit);
|
|
692
710
|
for (const [key, value] of headerEntries) {
|
|
693
711
|
if (key === "set-cookie") {
|
|
694
712
|
for (const setCookie of splitSetCookieString(value)) {
|
|
@@ -699,6 +717,17 @@ const NodeResponse = /* @__PURE__ */ (() => {
|
|
|
699
717
|
}
|
|
700
718
|
}
|
|
701
719
|
}
|
|
720
|
+
if (this.#headersObj) {
|
|
721
|
+
for (const [key, value] of this.#headersObj) {
|
|
722
|
+
if (key === "set-cookie") {
|
|
723
|
+
for (const setCookie of splitSetCookieString(value)) {
|
|
724
|
+
headers.push(["set-cookie", setCookie]);
|
|
725
|
+
}
|
|
726
|
+
} else {
|
|
727
|
+
headers.push([key, value]);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
702
731
|
const bodyInit = this.#body;
|
|
703
732
|
let body;
|
|
704
733
|
if (bodyInit) {
|
|
@@ -907,11 +936,7 @@ class NodeServer {
|
|
|
907
936
|
constructor(options) {
|
|
908
937
|
this.runtime = "node";
|
|
909
938
|
this.options = options;
|
|
910
|
-
const fetchHandler = wrapFetch(
|
|
911
|
-
this,
|
|
912
|
-
wrapFetchOnError(this.options.fetch, this.options.onError)
|
|
913
|
-
);
|
|
914
|
-
this.fetch = fetchHandler;
|
|
939
|
+
const fetchHandler = this.fetch = wrapFetch(this, [errorPlugin]);
|
|
915
940
|
const handler = (nodeReq, nodeRes) => {
|
|
916
941
|
const request = new NodeRequest({ req: nodeReq, res: nodeRes });
|
|
917
942
|
const res = fetchHandler(request);
|
|
@@ -930,6 +955,19 @@ class NodeServer {
|
|
|
930
955
|
this.serveOptions,
|
|
931
956
|
handler
|
|
932
957
|
) : NodeHttp.createServer(this.serveOptions, handler);
|
|
958
|
+
const upgradeHandler = this.options.upgrade;
|
|
959
|
+
if (upgradeHandler) {
|
|
960
|
+
server.on("upgrade", (nodeReq, socket, header) => {
|
|
961
|
+
const request = new NodeRequest({
|
|
962
|
+
req: nodeReq,
|
|
963
|
+
upgrade: { socket, header }
|
|
964
|
+
});
|
|
965
|
+
const res = upgradeHandler(request);
|
|
966
|
+
return res instanceof Promise ? res.then(
|
|
967
|
+
(resolvedRes) => sendNodeUpgradeResponse(socket, resolvedRes)
|
|
968
|
+
) : sendNodeUpgradeResponse(socket, res);
|
|
969
|
+
});
|
|
970
|
+
}
|
|
933
971
|
this.node = { server, handler };
|
|
934
972
|
if (!options.manual) {
|
|
935
973
|
this.serve();
|
|
@@ -973,4 +1011,4 @@ class NodeServer {
|
|
|
973
1011
|
}
|
|
974
1012
|
}
|
|
975
1013
|
|
|
976
|
-
export { NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders,
|
|
1014
|
+
export { NodeResponse as FastResponse, NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, serve, toNodeHandler };
|
|
@@ -5,9 +5,10 @@ import 'node:net';
|
|
|
5
5
|
import 'bun';
|
|
6
6
|
import '@cloudflare/workers-types';
|
|
7
7
|
|
|
8
|
-
declare const
|
|
8
|
+
declare const FastURL: typeof globalThis.URL;
|
|
9
|
+
declare const FastResponse: typeof globalThis.Response;
|
|
9
10
|
type ServiceWorkerHandler = (request: ServerRequest, event: FetchEvent) => Response | Promise<Response>;
|
|
10
11
|
declare function serve(options: ServerOptions): Server<ServiceWorkerHandler>;
|
|
11
12
|
|
|
12
|
-
export {
|
|
13
|
+
export { FastResponse, FastURL, serve };
|
|
13
14
|
export type { ServiceWorkerHandler };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { w as wrapFetch } from '../shared/srvx.
|
|
2
|
-
import {
|
|
1
|
+
import { w as wrapFetch } from '../shared/srvx.zEohKxBQ.mjs';
|
|
2
|
+
import { e as errorPlugin } from '../shared/srvx.CEIXM-sv.mjs';
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const FastURL = URL;
|
|
5
|
+
const FastResponse = Response;
|
|
5
6
|
const isBrowserWindow = typeof window !== "undefined" && typeof navigator !== "undefined";
|
|
6
7
|
const isServiceWorker = typeof self !== "undefined" && "skipWaiting" in self;
|
|
7
8
|
function serve(options) {
|
|
@@ -11,10 +12,7 @@ class ServiceWorkerServer {
|
|
|
11
12
|
constructor(options) {
|
|
12
13
|
this.runtime = "service-worker";
|
|
13
14
|
this.options = options;
|
|
14
|
-
const fetchHandler = wrapFetch(
|
|
15
|
-
this,
|
|
16
|
-
wrapFetchOnError(this.options.fetch, this.options.onError)
|
|
17
|
-
);
|
|
15
|
+
const fetchHandler = wrapFetch(this, [errorPlugin]);
|
|
18
16
|
this.fetch = (request, event) => {
|
|
19
17
|
Object.defineProperties(request, {
|
|
20
18
|
runtime: {
|
|
@@ -94,4 +92,4 @@ class ServiceWorkerServer {
|
|
|
94
92
|
}
|
|
95
93
|
}
|
|
96
94
|
|
|
97
|
-
export {
|
|
95
|
+
export { FastResponse, FastURL, serve };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const wsUpgradePlugin = (server) => {
|
|
2
|
+
const upgradeHandler = server.options.upgrade;
|
|
3
|
+
if (!upgradeHandler) {
|
|
4
|
+
return {};
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
fetch(request, next) {
|
|
8
|
+
if (request.headers.get("upgrade") === "websocket") {
|
|
9
|
+
return upgradeHandler(request);
|
|
10
|
+
}
|
|
11
|
+
return next();
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { wsUpgradePlugin as w };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const errorPlugin = (server) => {
|
|
2
|
+
const errorHandler = server.options.error;
|
|
3
|
+
if (!errorHandler) {
|
|
4
|
+
return {};
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
fetch(_request, next) {
|
|
8
|
+
try {
|
|
9
|
+
const res = next();
|
|
10
|
+
return res instanceof Promise ? res.catch((error) => errorHandler(error)) : res;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
return errorHandler(error);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { errorPlugin as e };
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
function resolvePortAndHost(opts) {
|
|
4
|
+
const _port = opts.port ?? globalThis.process?.env.PORT ?? 3e3;
|
|
5
|
+
const port = typeof _port === "number" ? _port : Number.parseInt(_port, 10);
|
|
6
|
+
const hostname = opts.hostname ?? globalThis.process?.env.HOST;
|
|
7
|
+
return { port, hostname };
|
|
8
|
+
}
|
|
9
|
+
function fmtURL(host, port, secure) {
|
|
10
|
+
if (!host || !port) {
|
|
11
|
+
return void 0;
|
|
12
|
+
}
|
|
13
|
+
if (host.includes(":")) {
|
|
14
|
+
host = `[${host}]`;
|
|
15
|
+
}
|
|
16
|
+
return `http${secure ? "s" : ""}://${host}:${port}/`;
|
|
17
|
+
}
|
|
18
|
+
function printListening(opts, url) {
|
|
19
|
+
if (!url || (opts.silent ?? globalThis.process?.env?.TEST)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const _url = new URL(url);
|
|
23
|
+
const allInterfaces = _url.hostname === "[::]" || _url.hostname === "0.0.0.0";
|
|
24
|
+
if (allInterfaces) {
|
|
25
|
+
_url.hostname = "localhost";
|
|
26
|
+
url = _url.href;
|
|
27
|
+
}
|
|
28
|
+
let listeningOn = `\u279C Listening on:`;
|
|
29
|
+
let additionalInfo = allInterfaces ? " (all interfaces)" : "";
|
|
30
|
+
if (globalThis.process.stdout?.isTTY) {
|
|
31
|
+
listeningOn = `\x1B[32m${listeningOn}\x1B[0m`;
|
|
32
|
+
url = `\x1B[36m${url}\x1B[0m`;
|
|
33
|
+
additionalInfo = `\x1B[2m${additionalInfo}\x1B[0m`;
|
|
34
|
+
}
|
|
35
|
+
console.log(` ${listeningOn} ${url}${additionalInfo}`);
|
|
36
|
+
}
|
|
37
|
+
function resolveTLSOptions(opts) {
|
|
38
|
+
if (!opts.tls || opts.protocol === "http") {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const cert = resolveCertOrKey(opts.tls.cert);
|
|
42
|
+
const key = resolveCertOrKey(opts.tls.key);
|
|
43
|
+
if (!cert && !key) {
|
|
44
|
+
if (opts.protocol === "https") {
|
|
45
|
+
throw new TypeError(
|
|
46
|
+
"TLS `cert` and `key` must be provided for `https` protocol."
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (!cert || !key) {
|
|
52
|
+
throw new TypeError("TLS `cert` and `key` must be provided together.");
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
cert,
|
|
56
|
+
key,
|
|
57
|
+
passphrase: opts.tls.passphrase
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function resolveCertOrKey(value) {
|
|
61
|
+
if (!value) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (typeof value !== "string") {
|
|
65
|
+
throw new TypeError(
|
|
66
|
+
"TLS certificate and key must be strings in PEM format or file paths."
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (value.startsWith("-----BEGIN ")) {
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
return readFileSync(value, "utf8");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const FastURL = /* @__PURE__ */ (() => {
|
|
76
|
+
const FastURL2 = class URL {
|
|
77
|
+
#originalURL;
|
|
78
|
+
#parsedURL;
|
|
79
|
+
constructor(url) {
|
|
80
|
+
this.#originalURL = url;
|
|
81
|
+
}
|
|
82
|
+
get _url() {
|
|
83
|
+
if (!this.#parsedURL) {
|
|
84
|
+
this.#parsedURL = new globalThis.URL(this.#originalURL);
|
|
85
|
+
}
|
|
86
|
+
return this.#parsedURL;
|
|
87
|
+
}
|
|
88
|
+
toString() {
|
|
89
|
+
return this._url.toString();
|
|
90
|
+
}
|
|
91
|
+
toJSON() {
|
|
92
|
+
return this.toString();
|
|
93
|
+
}
|
|
94
|
+
get pathname() {
|
|
95
|
+
if (this.#parsedURL) {
|
|
96
|
+
return this.#parsedURL.pathname;
|
|
97
|
+
}
|
|
98
|
+
if (!this._pathname) {
|
|
99
|
+
const url = this.#originalURL;
|
|
100
|
+
const protoIndex = url.indexOf("://");
|
|
101
|
+
if (protoIndex === -1) {
|
|
102
|
+
return this._url.pathname;
|
|
103
|
+
}
|
|
104
|
+
const pIndex = url.indexOf(
|
|
105
|
+
"/",
|
|
106
|
+
protoIndex + 4
|
|
107
|
+
/* :// */
|
|
108
|
+
);
|
|
109
|
+
if (pIndex === -1) {
|
|
110
|
+
return this._url.pathname;
|
|
111
|
+
}
|
|
112
|
+
const qIndex = this._urlqindex = url.indexOf("?", pIndex);
|
|
113
|
+
this._pathname = url.slice(pIndex, qIndex === -1 ? void 0 : qIndex);
|
|
114
|
+
}
|
|
115
|
+
return this._pathname;
|
|
116
|
+
}
|
|
117
|
+
set pathname(value) {
|
|
118
|
+
this._url.pathname = value;
|
|
119
|
+
}
|
|
120
|
+
get searchParams() {
|
|
121
|
+
if (this.#parsedURL) {
|
|
122
|
+
return this.#parsedURL.searchParams;
|
|
123
|
+
}
|
|
124
|
+
if (!this._query) {
|
|
125
|
+
this._query = new URLSearchParams(this.search);
|
|
126
|
+
}
|
|
127
|
+
return this._query;
|
|
128
|
+
}
|
|
129
|
+
get search() {
|
|
130
|
+
if (this.#parsedURL) {
|
|
131
|
+
return this.#parsedURL.search;
|
|
132
|
+
}
|
|
133
|
+
if (!this._search) {
|
|
134
|
+
const qIndex = this._urlqindex;
|
|
135
|
+
if (qIndex === -1) {
|
|
136
|
+
this._search = "";
|
|
137
|
+
} else {
|
|
138
|
+
this._search = qIndex === void 0 ? this._url.search : this.#originalURL.slice(this._urlqindex);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return this._search;
|
|
142
|
+
}
|
|
143
|
+
set search(value) {
|
|
144
|
+
this._url.search = value;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const slowProps = [
|
|
148
|
+
"hash",
|
|
149
|
+
"host",
|
|
150
|
+
"hostname",
|
|
151
|
+
"href",
|
|
152
|
+
"origin",
|
|
153
|
+
"password",
|
|
154
|
+
"port",
|
|
155
|
+
"protocol",
|
|
156
|
+
"username"
|
|
157
|
+
];
|
|
158
|
+
for (const prop of slowProps) {
|
|
159
|
+
Object.defineProperty(FastURL2.prototype, prop, {
|
|
160
|
+
get() {
|
|
161
|
+
return this._url[prop];
|
|
162
|
+
},
|
|
163
|
+
set(value) {
|
|
164
|
+
this._url[prop] = value;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
Object.setPrototypeOf(FastURL2, globalThis.URL);
|
|
169
|
+
return FastURL2;
|
|
170
|
+
})();
|
|
171
|
+
|
|
172
|
+
export { FastURL as F, resolvePortAndHost as a, fmtURL as f, printListening as p, resolveTLSOptions as r };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function wrapFetch(server, basePlugins) {
|
|
2
|
+
const plugins = [
|
|
3
|
+
...basePlugins || [],
|
|
4
|
+
...server.options.plugins || []
|
|
5
|
+
].map((plugin) => typeof plugin === "function" ? plugin(server) : plugin);
|
|
6
|
+
const middleware = plugins.filter((plugin) => plugin.fetch).map((plugin) => plugin.fetch);
|
|
7
|
+
const fetchHandler = server.options.fetch;
|
|
8
|
+
return middleware.length === 0 ? fetchHandler : (request) => callMiddleware(request, fetchHandler, middleware, 0);
|
|
9
|
+
}
|
|
10
|
+
function callMiddleware(request, fetchHandler, middleware, index) {
|
|
11
|
+
if (index === middleware.length) {
|
|
12
|
+
return fetchHandler(request);
|
|
13
|
+
}
|
|
14
|
+
return middleware[index](
|
|
15
|
+
request,
|
|
16
|
+
() => callMiddleware(request, fetchHandler, middleware, index + 1)
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { wrapFetch as w };
|
package/dist/types.d.mts
CHANGED
|
@@ -5,7 +5,14 @@ import * as Bun from 'bun';
|
|
|
5
5
|
import * as CF from '@cloudflare/workers-types';
|
|
6
6
|
|
|
7
7
|
type MaybePromise<T> = T | Promise<T>;
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Faster URL constructor with lazy access to pathname and search params (For Node, Deno, and Bun).
|
|
10
|
+
*/
|
|
11
|
+
declare const FastURL: typeof globalThis.URL;
|
|
12
|
+
/**
|
|
13
|
+
* Faster Response constructor optimized for Node.js (same as Response for other runtimes).
|
|
14
|
+
*/
|
|
15
|
+
declare const FastResponse: typeof globalThis.Response;
|
|
9
16
|
/**
|
|
10
17
|
* Create a new server instance.
|
|
11
18
|
*/
|
|
@@ -22,6 +29,16 @@ interface ServerOptions {
|
|
|
22
29
|
* The fetch handler handles incoming requests.
|
|
23
30
|
*/
|
|
24
31
|
fetch: ServerHandler;
|
|
32
|
+
/**
|
|
33
|
+
* Handle websocket upgrades.
|
|
34
|
+
*/
|
|
35
|
+
upgrade?: ServerHandler;
|
|
36
|
+
/**
|
|
37
|
+
* Handle lifecycle errors.
|
|
38
|
+
*
|
|
39
|
+
* @note This handler will set built-in Bun and Deno error handler.
|
|
40
|
+
*/
|
|
41
|
+
error?: ErrorHandler;
|
|
25
42
|
/**
|
|
26
43
|
* Server plugins.
|
|
27
44
|
*/
|
|
@@ -81,12 +98,6 @@ interface ServerOptions {
|
|
|
81
98
|
*/
|
|
82
99
|
passphrase?: string;
|
|
83
100
|
};
|
|
84
|
-
/**
|
|
85
|
-
* Runtime agnostic error handler (optional).
|
|
86
|
-
*
|
|
87
|
-
* @note This handler will take precedence over runtime specific error handlers.
|
|
88
|
-
*/
|
|
89
|
-
onError?: ErrorHandler;
|
|
90
101
|
/**
|
|
91
102
|
* Node.js server options.
|
|
92
103
|
*/
|
|
@@ -169,21 +180,10 @@ interface Server<Handler = ServerHandler> {
|
|
|
169
180
|
close(closeActiveConnections?: boolean): Promise<void>;
|
|
170
181
|
}
|
|
171
182
|
type ServerPlugin = (server: Server) => ServerPluginInstance;
|
|
183
|
+
type ServerMiddleware = (request: ServerRequest, next: () => Response | Promise<Response>) => Response | Promise<Response>;
|
|
172
184
|
interface ServerPluginInstance {
|
|
173
|
-
/**
|
|
174
|
-
* Plugin display name
|
|
175
|
-
*/
|
|
176
185
|
name?: string;
|
|
177
|
-
|
|
178
|
-
* Hook to allow running logic before user fetch handler
|
|
179
|
-
* If an response value is returned, user fetch handler and the next plugins will be skipped.
|
|
180
|
-
*/
|
|
181
|
-
request?: (request: ServerRequest) => MaybePromise<Response | void>;
|
|
182
|
-
/**
|
|
183
|
-
* Hook to allow running logic after user fetch handler
|
|
184
|
-
* If a response value is returned, user response and the next plugins will be skipped.
|
|
185
|
-
*/
|
|
186
|
-
response?: (request: ServerRequest, response: Response) => MaybePromise<void | Response>;
|
|
186
|
+
fetch?: ServerMiddleware;
|
|
187
187
|
}
|
|
188
188
|
interface ServerRuntimeContext {
|
|
189
189
|
name: "node" | "deno" | "bun" | "cloudflare" | (string & {});
|
|
@@ -231,5 +231,5 @@ type DenoFetchHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.Net
|
|
|
231
231
|
type NodeHttpHandler = (nodeReq: NodeHttp.IncomingMessage, nodeRes: NodeHttp.ServerResponse) => void | Promise<void>;
|
|
232
232
|
type CloudflareFetchHandler = CF.ExportedHandlerFetchHandler;
|
|
233
233
|
|
|
234
|
-
export {
|
|
235
|
-
export type { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FetchHandler, NodeHttpHandler, Server, ServerHandler, ServerOptions, ServerPlugin, ServerPluginInstance, ServerRequest, ServerRuntimeContext };
|
|
234
|
+
export { FastResponse, FastURL, serve };
|
|
235
|
+
export type { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FetchHandler, NodeHttpHandler, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerPluginInstance, ServerRequest, ServerRuntimeContext };
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "srvx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Universal Server API based on web platform standards. Works seamlessly with Deno, Bun and Node.js.",
|
|
5
|
-
"repository": "h3js/srvx",
|
|
6
5
|
"homepage": "https://srvx.h3.dev",
|
|
6
|
+
"repository": "h3js/srvx",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"type": "module",
|
|
@@ -31,10 +31,14 @@
|
|
|
31
31
|
],
|
|
32
32
|
"scripts": {
|
|
33
33
|
"bench:node": "node test/bench-node/_run.mjs",
|
|
34
|
+
"bench:url:bun": "bun run ./test/url.bench.ts",
|
|
35
|
+
"bench:url:deno": "deno run -A ./test/url.bench.ts",
|
|
36
|
+
"bench:url:node": "pnpm node-ts --expose-gc --allow-natives-syntax ./test/url.bench.ts",
|
|
34
37
|
"build": "unbuild",
|
|
35
38
|
"dev": "vitest dev",
|
|
36
39
|
"lint": "eslint . && prettier -c .",
|
|
37
40
|
"lint:fix": "automd && eslint . --fix && prettier -w .",
|
|
41
|
+
"node-ts": "node --disable-warning=ExperimentalWarning --experimental-strip-types",
|
|
38
42
|
"prepack": "pnpm build",
|
|
39
43
|
"play:bun": "bun playground/app.mjs",
|
|
40
44
|
"play:cf": "pnpx wrangler dev playground/app.mjs",
|
|
@@ -55,6 +59,7 @@
|
|
|
55
59
|
"devDependencies": {
|
|
56
60
|
"@cloudflare/workers-types": "^4.20250423.0",
|
|
57
61
|
"@hono/node-server": "^1.14.1",
|
|
62
|
+
"@mitata/counters": "^0.0.8",
|
|
58
63
|
"@mjackson/node-fetch-server": "^0.6.1",
|
|
59
64
|
"@types/bun": "^1.2.10",
|
|
60
65
|
"@types/deno": "^2.2.0",
|
|
@@ -67,7 +72,7 @@
|
|
|
67
72
|
"eslint-config-unjs": "^0.4.2",
|
|
68
73
|
"execa": "^9.5.2",
|
|
69
74
|
"get-port-please": "^3.1.2",
|
|
70
|
-
"
|
|
75
|
+
"mitata": "^1.0.34",
|
|
71
76
|
"prettier": "^3.5.3",
|
|
72
77
|
"typescript": "^5.8.3",
|
|
73
78
|
"unbuild": "^3.5.0",
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
function wrapFetchOnError(fetchHandler, onError) {
|
|
2
|
-
if (!onError) return fetchHandler;
|
|
3
|
-
return (...params) => {
|
|
4
|
-
try {
|
|
5
|
-
const result = fetchHandler(...params);
|
|
6
|
-
if (result instanceof Promise) {
|
|
7
|
-
return result.catch(onError);
|
|
8
|
-
}
|
|
9
|
-
return result;
|
|
10
|
-
} catch (error) {
|
|
11
|
-
return onError(error);
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export { wrapFetchOnError as w };
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
function wrapFetch(server, fetchHandler) {
|
|
2
|
-
const plugins = server.options.plugins;
|
|
3
|
-
if (!plugins?.length) {
|
|
4
|
-
return fetchHandler;
|
|
5
|
-
}
|
|
6
|
-
const requestHooks = [];
|
|
7
|
-
const responseHooks = [];
|
|
8
|
-
for (const ctor of plugins) {
|
|
9
|
-
const plugin = typeof ctor === "function" ? ctor(server) : ctor;
|
|
10
|
-
if (plugin.request) {
|
|
11
|
-
requestHooks.push(plugin.request);
|
|
12
|
-
}
|
|
13
|
-
if (plugin.response) {
|
|
14
|
-
responseHooks.push(plugin.response);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
const hasRequestHooks = requestHooks.length > 0;
|
|
18
|
-
const hasResponseHooks = responseHooks.length > 0;
|
|
19
|
-
if (!hasRequestHooks && !hasResponseHooks) {
|
|
20
|
-
return fetchHandler;
|
|
21
|
-
}
|
|
22
|
-
return (request) => {
|
|
23
|
-
let resValue;
|
|
24
|
-
let resPromise;
|
|
25
|
-
if (hasRequestHooks) {
|
|
26
|
-
for (const reqHook of requestHooks) {
|
|
27
|
-
if (resPromise) {
|
|
28
|
-
resPromise = resPromise.then((res) => res || reqHook(request));
|
|
29
|
-
} else {
|
|
30
|
-
const res = reqHook(request);
|
|
31
|
-
if (res) {
|
|
32
|
-
if (res instanceof Promise) {
|
|
33
|
-
resPromise = res;
|
|
34
|
-
} else {
|
|
35
|
-
return res;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
if (resPromise) {
|
|
42
|
-
resPromise = resPromise.then((res) => res || fetchHandler(request));
|
|
43
|
-
} else {
|
|
44
|
-
const res = fetchHandler(request);
|
|
45
|
-
if (res instanceof Promise) {
|
|
46
|
-
resPromise = res;
|
|
47
|
-
} else {
|
|
48
|
-
resValue = res;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (hasResponseHooks) {
|
|
52
|
-
for (const resHook of responseHooks) {
|
|
53
|
-
if (resPromise) {
|
|
54
|
-
resPromise = resPromise.then((res) => {
|
|
55
|
-
if (res) {
|
|
56
|
-
resValue = res;
|
|
57
|
-
}
|
|
58
|
-
return resHook(request, resValue);
|
|
59
|
-
});
|
|
60
|
-
} else {
|
|
61
|
-
const res = resHook(request, resValue);
|
|
62
|
-
if (res) {
|
|
63
|
-
if (res instanceof Promise) {
|
|
64
|
-
resPromise = res;
|
|
65
|
-
} else {
|
|
66
|
-
resValue = res;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return resPromise ? resPromise.then((res) => res || resValue) : resValue;
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export { wrapFetch as w };
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
|
|
3
|
-
function resolvePortAndHost(opts) {
|
|
4
|
-
const _port = opts.port ?? globalThis.process?.env.PORT ?? 3e3;
|
|
5
|
-
const port = typeof _port === "number" ? _port : Number.parseInt(_port, 10);
|
|
6
|
-
const hostname = opts.hostname ?? globalThis.process?.env.HOST;
|
|
7
|
-
return { port, hostname };
|
|
8
|
-
}
|
|
9
|
-
function fmtURL(host, port, secure) {
|
|
10
|
-
if (!host || !port) {
|
|
11
|
-
return void 0;
|
|
12
|
-
}
|
|
13
|
-
if (host.includes(":")) {
|
|
14
|
-
host = `[${host}]`;
|
|
15
|
-
}
|
|
16
|
-
return `http${secure ? "s" : ""}://${host}:${port}/`;
|
|
17
|
-
}
|
|
18
|
-
function printListening(opts, url) {
|
|
19
|
-
if (!url || (opts.silent ?? globalThis.process?.env?.TEST)) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const _url = new URL(url);
|
|
23
|
-
const allInterfaces = _url.hostname === "[::]" || _url.hostname === "0.0.0.0";
|
|
24
|
-
if (allInterfaces) {
|
|
25
|
-
_url.hostname = "localhost";
|
|
26
|
-
url = _url.href;
|
|
27
|
-
}
|
|
28
|
-
let listeningOn = `\u279C Listening on:`;
|
|
29
|
-
let additionalInfo = allInterfaces ? " (all interfaces)" : "";
|
|
30
|
-
if (globalThis.process.stdout?.isTTY) {
|
|
31
|
-
listeningOn = `\x1B[32m${listeningOn}\x1B[0m`;
|
|
32
|
-
url = `\x1B[36m${url}\x1B[0m`;
|
|
33
|
-
additionalInfo = `\x1B[2m${additionalInfo}\x1B[0m`;
|
|
34
|
-
}
|
|
35
|
-
console.log(` ${listeningOn} ${url}${additionalInfo}`);
|
|
36
|
-
}
|
|
37
|
-
function resolveTLSOptions(opts) {
|
|
38
|
-
if (!opts.tls || opts.protocol === "http") {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
const cert = resolveCertOrKey(opts.tls.cert);
|
|
42
|
-
const key = resolveCertOrKey(opts.tls.key);
|
|
43
|
-
if (!cert && !key) {
|
|
44
|
-
if (opts.protocol === "https") {
|
|
45
|
-
throw new TypeError(
|
|
46
|
-
"TLS `cert` and `key` must be provided for `https` protocol."
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (!cert || !key) {
|
|
52
|
-
throw new TypeError("TLS `cert` and `key` must be provided together.");
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
cert,
|
|
56
|
-
key,
|
|
57
|
-
passphrase: opts.tls.passphrase
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
function resolveCertOrKey(value) {
|
|
61
|
-
if (!value) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
if (typeof value !== "string") {
|
|
65
|
-
throw new TypeError(
|
|
66
|
-
"TLS certificate and key must be strings in PEM format or file paths."
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
if (value.startsWith("-----BEGIN ")) {
|
|
70
|
-
return value;
|
|
71
|
-
}
|
|
72
|
-
return readFileSync(value, "utf8");
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export { resolvePortAndHost as a, fmtURL as f, printListening as p, resolveTLSOptions as r };
|