srvx 0.11.3 → 0.11.5
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 +2 -1
- package/dist/adapters/bun.mjs +10 -2
- package/dist/adapters/bunny.d.mts +8 -0
- package/dist/adapters/bunny.mjs +55 -0
- package/dist/adapters/deno.d.mts +2 -1
- package/dist/adapters/deno.mjs +10 -2
- package/dist/adapters/generic.mjs +2 -0
- package/dist/adapters/node.mjs +10 -3
- package/dist/cli.mjs +1 -1
- package/dist/loader.mjs +13 -5
- package/dist/types.d.mts +8 -2
- package/package.json +11 -10
package/dist/adapters/bun.d.mts
CHANGED
|
@@ -10,8 +10,9 @@ declare class BunServer implements Server<BunFetchHandler> {
|
|
|
10
10
|
readonly runtime = "bun";
|
|
11
11
|
readonly options: Server["options"];
|
|
12
12
|
readonly bun: Server["bun"];
|
|
13
|
-
readonly serveOptions: bun.Serve.Options<any
|
|
13
|
+
readonly serveOptions: bun.Serve.Options<any> | undefined;
|
|
14
14
|
readonly fetch: BunFetchHandler;
|
|
15
|
+
readonly waitUntil?: Server["waitUntil"];
|
|
15
16
|
constructor(options: ServerOptions);
|
|
16
17
|
serve(): Promise<this>;
|
|
17
18
|
get url(): string | undefined;
|
package/dist/adapters/bun.mjs
CHANGED
|
@@ -11,6 +11,7 @@ var BunServer = class {
|
|
|
11
11
|
bun = {};
|
|
12
12
|
serveOptions;
|
|
13
13
|
fetch;
|
|
14
|
+
waitUntil;
|
|
14
15
|
#wait;
|
|
15
16
|
constructor(options) {
|
|
16
17
|
this.options = {
|
|
@@ -20,10 +21,17 @@ var BunServer = class {
|
|
|
20
21
|
for (const plugin of options.plugins || []) plugin(this);
|
|
21
22
|
gracefulShutdownPlugin(this);
|
|
22
23
|
const fetchHandler = wrapFetch(this);
|
|
24
|
+
const loader = globalThis.__srvxLoader__;
|
|
25
|
+
if (loader) {
|
|
26
|
+
this.fetch = fetchHandler;
|
|
27
|
+
loader(fetchHandler);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
23
30
|
this.#wait = createWaitUntil();
|
|
31
|
+
this.waitUntil = this.#wait.waitUntil;
|
|
24
32
|
this.fetch = (request, server) => {
|
|
25
33
|
Object.defineProperties(request, {
|
|
26
|
-
waitUntil: { value: this.#wait
|
|
34
|
+
waitUntil: { value: this.#wait?.waitUntil },
|
|
27
35
|
runtime: {
|
|
28
36
|
enumerable: true,
|
|
29
37
|
value: {
|
|
@@ -72,7 +80,7 @@ var BunServer = class {
|
|
|
72
80
|
return Promise.resolve(this);
|
|
73
81
|
}
|
|
74
82
|
async close(closeAll) {
|
|
75
|
-
await Promise.all([this.#wait
|
|
83
|
+
await Promise.all([this.#wait?.wait(), Promise.resolve(this.bun?.server?.stop(closeAll))]);
|
|
76
84
|
}
|
|
77
85
|
};
|
|
78
86
|
export { FastResponse, FastURL, serve };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Server, ServerOptions } from "../types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/bunny.d.ts
|
|
4
|
+
declare const FastURL: typeof globalThis.URL;
|
|
5
|
+
declare const FastResponse: typeof globalThis.Response;
|
|
6
|
+
declare function serve(options: ServerOptions): Server;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { FastResponse, FastURL, serve };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { t as createWaitUntil } from "../_chunks/_utils2.mjs";
|
|
2
|
+
import { r as wrapFetch, t as errorPlugin } from "../_chunks/_plugins.mjs";
|
|
3
|
+
const FastURL = URL;
|
|
4
|
+
const FastResponse = Response;
|
|
5
|
+
function serve(options) {
|
|
6
|
+
return new BunnyServer(options);
|
|
7
|
+
}
|
|
8
|
+
var BunnyServer = class {
|
|
9
|
+
runtime = "bunny";
|
|
10
|
+
options;
|
|
11
|
+
fetch;
|
|
12
|
+
_started = false;
|
|
13
|
+
#wait;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = {
|
|
16
|
+
...options,
|
|
17
|
+
middleware: [...options.middleware || []]
|
|
18
|
+
};
|
|
19
|
+
for (const plugin of options.plugins || []) plugin(this);
|
|
20
|
+
errorPlugin(this);
|
|
21
|
+
const fetchHandler = wrapFetch(this);
|
|
22
|
+
this.#wait = createWaitUntil();
|
|
23
|
+
this.fetch = (request) => {
|
|
24
|
+
Object.defineProperties(request, {
|
|
25
|
+
waitUntil: { value: this.#wait?.waitUntil },
|
|
26
|
+
runtime: {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
value: { name: "bunny" }
|
|
29
|
+
},
|
|
30
|
+
ip: {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get() {
|
|
33
|
+
return request.headers.get("x-real-ip");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return fetchHandler(request);
|
|
38
|
+
};
|
|
39
|
+
if (!options.manual) this.serve();
|
|
40
|
+
}
|
|
41
|
+
serve() {
|
|
42
|
+
if (typeof Bunny !== "undefined" && Bunny.v1?.serve) {
|
|
43
|
+
if (this._started) return;
|
|
44
|
+
this._started = true;
|
|
45
|
+
Bunny.v1.serve(this.fetch);
|
|
46
|
+
} else throw new Error("[srvx] Bunny runtime not detected.");
|
|
47
|
+
}
|
|
48
|
+
ready() {
|
|
49
|
+
return Promise.resolve(this);
|
|
50
|
+
}
|
|
51
|
+
async close() {
|
|
52
|
+
await this.#wait?.wait();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
export { FastResponse, FastURL, serve };
|
package/dist/adapters/deno.d.mts
CHANGED
|
@@ -9,8 +9,9 @@ declare class DenoServer implements Server<DenoFetchHandler> {
|
|
|
9
9
|
readonly runtime = "deno";
|
|
10
10
|
readonly options: Server["options"];
|
|
11
11
|
readonly deno: Server["deno"];
|
|
12
|
-
readonly serveOptions: Deno.ServeTcpOptions | (Deno.ServeTcpOptions & Deno.TlsCertifiedKeyPem);
|
|
12
|
+
readonly serveOptions: Deno.ServeTcpOptions | (Deno.ServeTcpOptions & Deno.TlsCertifiedKeyPem) | undefined;
|
|
13
13
|
readonly fetch: DenoFetchHandler;
|
|
14
|
+
readonly waitUntil?: Server["waitUntil"];
|
|
14
15
|
constructor(options: ServerOptions);
|
|
15
16
|
serve(): Promise<this>;
|
|
16
17
|
get url(): string | undefined;
|
package/dist/adapters/deno.mjs
CHANGED
|
@@ -11,6 +11,7 @@ var DenoServer = class {
|
|
|
11
11
|
deno = {};
|
|
12
12
|
serveOptions;
|
|
13
13
|
fetch;
|
|
14
|
+
waitUntil;
|
|
14
15
|
#listeningPromise;
|
|
15
16
|
#listeningInfo;
|
|
16
17
|
#wait;
|
|
@@ -22,10 +23,17 @@ var DenoServer = class {
|
|
|
22
23
|
for (const plugin of options.plugins || []) plugin(this);
|
|
23
24
|
gracefulShutdownPlugin(this);
|
|
24
25
|
const fetchHandler = wrapFetch(this);
|
|
26
|
+
const loader = globalThis.__srvxLoader__;
|
|
27
|
+
if (loader) {
|
|
28
|
+
this.fetch = fetchHandler;
|
|
29
|
+
loader(fetchHandler);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
25
32
|
this.#wait = createWaitUntil();
|
|
33
|
+
this.waitUntil = this.#wait.waitUntil;
|
|
26
34
|
this.fetch = (request, info) => {
|
|
27
35
|
Object.defineProperties(request, {
|
|
28
|
-
waitUntil: { value: this.#wait
|
|
36
|
+
waitUntil: { value: this.#wait?.waitUntil },
|
|
29
37
|
runtime: {
|
|
30
38
|
enumerable: true,
|
|
31
39
|
value: {
|
|
@@ -81,7 +89,7 @@ var DenoServer = class {
|
|
|
81
89
|
return Promise.resolve(this.#listeningPromise).then(() => this);
|
|
82
90
|
}
|
|
83
91
|
async close() {
|
|
84
|
-
await Promise.all([this.#wait
|
|
92
|
+
await Promise.all([this.#wait?.wait(), Promise.resolve(this.deno?.server?.shutdown())]);
|
|
85
93
|
}
|
|
86
94
|
};
|
|
87
95
|
export { FastResponse, FastURL, serve };
|
|
@@ -9,6 +9,7 @@ var GenericServer = class {
|
|
|
9
9
|
runtime = "generic";
|
|
10
10
|
options;
|
|
11
11
|
fetch;
|
|
12
|
+
waitUntil;
|
|
12
13
|
#wait;
|
|
13
14
|
constructor(options) {
|
|
14
15
|
this.options = {
|
|
@@ -18,6 +19,7 @@ var GenericServer = class {
|
|
|
18
19
|
for (const plugin of options.plugins || []) plugin(this);
|
|
19
20
|
errorPlugin(this);
|
|
20
21
|
this.#wait = createWaitUntil();
|
|
22
|
+
this.waitUntil = this.#wait.waitUntil;
|
|
21
23
|
const fetchHandler = wrapFetch(this);
|
|
22
24
|
this.fetch = (request) => {
|
|
23
25
|
Object.defineProperties(request, { waitUntil: { value: this.#wait.waitUntil } });
|
package/dist/adapters/node.mjs
CHANGED
|
@@ -660,6 +660,7 @@ var NodeServer = class {
|
|
|
660
660
|
node;
|
|
661
661
|
serveOptions;
|
|
662
662
|
fetch;
|
|
663
|
+
waitUntil;
|
|
663
664
|
#isSecure;
|
|
664
665
|
#listeningPromise;
|
|
665
666
|
#wait;
|
|
@@ -670,15 +671,21 @@ var NodeServer = class {
|
|
|
670
671
|
};
|
|
671
672
|
for (const plugin of options.plugins || []) plugin(this);
|
|
672
673
|
errorPlugin(this);
|
|
673
|
-
gracefulShutdownPlugin(this);
|
|
674
674
|
const fetchHandler = this.fetch = wrapFetch(this);
|
|
675
|
+
const loader = globalThis.__srvxLoader__;
|
|
676
|
+
if (loader) {
|
|
677
|
+
loader(fetchHandler);
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
gracefulShutdownPlugin(this);
|
|
675
681
|
this.#wait = createWaitUntil();
|
|
682
|
+
this.waitUntil = this.#wait.waitUntil;
|
|
676
683
|
const handler = (nodeReq, nodeRes) => {
|
|
677
684
|
const request = new NodeRequest({
|
|
678
685
|
req: nodeReq,
|
|
679
686
|
res: nodeRes
|
|
680
687
|
});
|
|
681
|
-
request.waitUntil = this.#wait
|
|
688
|
+
request.waitUntil = this.#wait?.waitUntil;
|
|
682
689
|
const res = fetchHandler(request);
|
|
683
690
|
return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
|
|
684
691
|
};
|
|
@@ -728,7 +735,7 @@ var NodeServer = class {
|
|
|
728
735
|
return Promise.resolve(this.#listeningPromise).then(() => this);
|
|
729
736
|
}
|
|
730
737
|
async close(closeAll) {
|
|
731
|
-
await Promise.all([this.#wait
|
|
738
|
+
await Promise.all([this.#wait?.wait(), new Promise((resolve, reject) => {
|
|
732
739
|
const server = this.node?.server;
|
|
733
740
|
if (server && closeAll && "closeAllConnections" in server) server.closeAllConnections();
|
|
734
741
|
if (!server || !server.listening) return resolve();
|
package/dist/cli.mjs
CHANGED
package/dist/loader.mjs
CHANGED
|
@@ -34,12 +34,14 @@ async function loadServerEntry(opts) {
|
|
|
34
34
|
}
|
|
35
35
|
const url = entry.startsWith("file://") ? entry : pathToFileURL(resolve(entry)).href;
|
|
36
36
|
let mod;
|
|
37
|
-
let
|
|
37
|
+
let interceptedNodeHandler;
|
|
38
|
+
let interceptedFetchHandler;
|
|
38
39
|
try {
|
|
39
40
|
if (opts.interceptHttpListen !== false) {
|
|
40
41
|
const loaded = await interceptListen(() => import(url));
|
|
41
42
|
mod = loaded.res;
|
|
42
|
-
|
|
43
|
+
interceptedNodeHandler = loaded.listenHandler;
|
|
44
|
+
interceptedFetchHandler = loaded.fetchHandler;
|
|
43
45
|
} else mod = await import(url);
|
|
44
46
|
} catch (error) {
|
|
45
47
|
if (error?.code === "ERR_UNKNOWN_FILE_EXTENSION") {
|
|
@@ -50,11 +52,11 @@ async function loadServerEntry(opts) {
|
|
|
50
52
|
throw error;
|
|
51
53
|
}
|
|
52
54
|
mod = await opts?.onLoad?.(mod) || mod;
|
|
53
|
-
let fetchHandler = mod?.fetch || mod?.default?.fetch || mod?.default?.default?.fetch;
|
|
55
|
+
let fetchHandler = mod?.fetch || mod?.default?.fetch || mod?.default?.default?.fetch || interceptedFetchHandler;
|
|
54
56
|
if (!fetchHandler && typeof mod?.default === "function" && mod.default.length < 2) fetchHandler = mod.default;
|
|
55
57
|
let nodeCompat = false;
|
|
56
58
|
if (!fetchHandler && opts.nodeCompat !== false) {
|
|
57
|
-
const nodeHandler =
|
|
59
|
+
const nodeHandler = interceptedNodeHandler || (typeof mod?.default === "function" ? mod.default : void 0);
|
|
58
60
|
if (nodeHandler) {
|
|
59
61
|
nodeCompat = true;
|
|
60
62
|
const { fetchNodeHandler } = await import("srvx/node");
|
|
@@ -74,6 +76,10 @@ async function interceptListen(cb) {
|
|
|
74
76
|
const originalListen = nodeHTTP$1.Server.prototype.listen;
|
|
75
77
|
let res;
|
|
76
78
|
let listenHandler;
|
|
79
|
+
let fetchHandler;
|
|
80
|
+
globalThis.__srvxLoader__ = (handler) => {
|
|
81
|
+
fetchHandler = handler;
|
|
82
|
+
};
|
|
77
83
|
try {
|
|
78
84
|
nodeHTTP$1.Server.prototype.listen = function(arg1, arg2) {
|
|
79
85
|
listenHandler = this._events.request;
|
|
@@ -96,10 +102,12 @@ async function interceptListen(cb) {
|
|
|
96
102
|
res = await cb();
|
|
97
103
|
} finally {
|
|
98
104
|
nodeHTTP$1.Server.prototype.listen = originalListen;
|
|
105
|
+
delete globalThis.__srvxLoader__;
|
|
99
106
|
}
|
|
100
107
|
return {
|
|
101
108
|
res,
|
|
102
|
-
listenHandler
|
|
109
|
+
listenHandler,
|
|
110
|
+
fetchHandler
|
|
103
111
|
};
|
|
104
112
|
});
|
|
105
113
|
_interceptQueue = result.catch(() => {});
|
package/dist/types.d.mts
CHANGED
|
@@ -154,7 +154,7 @@ interface Server<Handler = ServerHandler> {
|
|
|
154
154
|
/**
|
|
155
155
|
* Current runtime name
|
|
156
156
|
*/
|
|
157
|
-
readonly runtime: "node" | "deno" | "bun" | "cloudflare" | "service-worker" | "aws-lambda" | "generic";
|
|
157
|
+
readonly runtime: "node" | "deno" | "bun" | "bunny" | "cloudflare" | "service-worker" | "aws-lambda" | "generic";
|
|
158
158
|
/**
|
|
159
159
|
* Server options
|
|
160
160
|
*/
|
|
@@ -198,6 +198,12 @@ interface Server<Handler = ServerHandler> {
|
|
|
198
198
|
*/
|
|
199
199
|
ready(): Promise<Server<Handler>>;
|
|
200
200
|
/**
|
|
201
|
+
* Register a background task that the server should await before closing.
|
|
202
|
+
*
|
|
203
|
+
* Same as `request.waitUntil` but available at the server level for use outside of request handlers.
|
|
204
|
+
*/
|
|
205
|
+
readonly waitUntil?: (promise: Promise<unknown>) => void;
|
|
206
|
+
/**
|
|
201
207
|
* Stop listening to prevent new connections from being accepted.
|
|
202
208
|
*
|
|
203
209
|
* By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops.
|
|
@@ -208,7 +214,7 @@ interface Server<Handler = ServerHandler> {
|
|
|
208
214
|
close(closeActiveConnections?: boolean): Promise<void>;
|
|
209
215
|
}
|
|
210
216
|
interface ServerRuntimeContext {
|
|
211
|
-
name: "node" | "deno" | "bun" | "cloudflare" | "aws-lambda" | (string & {});
|
|
217
|
+
name: "node" | "deno" | "bun" | "bunny" | "cloudflare" | "aws-lambda" | (string & {});
|
|
212
218
|
/**
|
|
213
219
|
* Underlying Node.js server request info.
|
|
214
220
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "srvx",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.5",
|
|
4
4
|
"description": "Universal Server.",
|
|
5
5
|
"homepage": "https://srvx.h3.dev",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"./bun": "./dist/adapters/bun.mjs",
|
|
21
21
|
"./node": "./dist/adapters/node.mjs",
|
|
22
22
|
"./cloudflare": "./dist/adapters/cloudflare.mjs",
|
|
23
|
+
"./bunny": "./dist/adapters/bunny.mjs",
|
|
23
24
|
"./generic": "./dist/adapters/generic.mjs",
|
|
24
25
|
"./service-worker": "./dist/adapters/service-worker.mjs",
|
|
25
26
|
"./aws-lambda": "./dist/adapters/aws-lambda.mjs",
|
|
@@ -58,18 +59,18 @@
|
|
|
58
59
|
"vitest": "vitest"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
|
-
"@cloudflare/workers-types": "^4.
|
|
62
|
+
"@cloudflare/workers-types": "^4.20260217.0",
|
|
62
63
|
"@hono/node-server": "^1.19.9",
|
|
63
64
|
"@mitata/counters": "^0.0.8",
|
|
64
65
|
"@mjackson/node-fetch-server": "^0.7.0",
|
|
65
66
|
"@types/aws-lambda": "^8.10.160",
|
|
66
|
-
"@types/bun": "^1.3.
|
|
67
|
+
"@types/bun": "^1.3.9",
|
|
67
68
|
"@types/deno": "^2.5.0",
|
|
68
69
|
"@types/express": "^5.0.6",
|
|
69
70
|
"@types/node": "^25.2.3",
|
|
70
71
|
"@types/node-forge": "^1.3.14",
|
|
71
|
-
"@types/serviceworker": "^0.0.
|
|
72
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
72
|
+
"@types/serviceworker": "^0.0.191",
|
|
73
|
+
"@typescript/native-preview": "^7.0.0-dev.20260217.1",
|
|
73
74
|
"@vitest/coverage-v8": "^4.0.18",
|
|
74
75
|
"@whatwg-node/server": "^0.10.18",
|
|
75
76
|
"automd": "^0.4.3",
|
|
@@ -83,12 +84,12 @@
|
|
|
83
84
|
"mitata": "^1.0.34",
|
|
84
85
|
"node-forge": "^1.3.3",
|
|
85
86
|
"obuild": "^0.4.27",
|
|
86
|
-
"oxfmt": "^0.
|
|
87
|
-
"oxlint": "^1.
|
|
88
|
-
"srvx-release": "npm:srvx@^0.
|
|
87
|
+
"oxfmt": "^0.33.0",
|
|
88
|
+
"oxlint": "^1.48.0",
|
|
89
|
+
"srvx-release": "npm:srvx@^0.11.4",
|
|
89
90
|
"tslib": "^2.8.1",
|
|
90
91
|
"typescript": "^5.9.3",
|
|
91
|
-
"undici": "^7.
|
|
92
|
+
"undici": "^7.22.0",
|
|
92
93
|
"vitest": "^4.0.18"
|
|
93
94
|
},
|
|
94
95
|
"resolutions": {
|
|
@@ -97,5 +98,5 @@
|
|
|
97
98
|
"engines": {
|
|
98
99
|
"node": ">=20.16.0"
|
|
99
100
|
},
|
|
100
|
-
"packageManager": "pnpm@10.29.
|
|
101
|
+
"packageManager": "pnpm@10.29.3"
|
|
101
102
|
}
|