srvx 0.11.6 → 0.11.7

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.
@@ -24,7 +24,7 @@ var BunServer = class {
24
24
  const loader = globalThis.__srvxLoader__;
25
25
  if (loader) {
26
26
  this.fetch = fetchHandler;
27
- loader(fetchHandler);
27
+ loader({ server: this });
28
28
  return;
29
29
  }
30
30
  this.#wait = createWaitUntil();
@@ -26,7 +26,7 @@ var DenoServer = class {
26
26
  const loader = globalThis.__srvxLoader__;
27
27
  if (loader) {
28
28
  this.fetch = fetchHandler;
29
- loader(fetchHandler);
29
+ loader({ server: this });
30
30
  return;
31
31
  }
32
32
  this.#wait = createWaitUntil();
@@ -672,14 +672,6 @@ var NodeServer = class {
672
672
  for (const plugin of options.plugins || []) plugin(this);
673
673
  errorPlugin(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);
681
- this.#wait = createWaitUntil();
682
- this.waitUntil = this.#wait.waitUntil;
683
675
  const handler = (nodeReq, nodeRes) => {
684
676
  const request = new NodeRequest({
685
677
  req: nodeReq,
@@ -689,6 +681,18 @@ var NodeServer = class {
689
681
  const res = fetchHandler(request);
690
682
  return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
691
683
  };
684
+ this.node = {
685
+ handler,
686
+ server: void 0
687
+ };
688
+ const loader = globalThis.__srvxLoader__;
689
+ if (loader) {
690
+ loader({ server: this });
691
+ return;
692
+ }
693
+ gracefulShutdownPlugin(this);
694
+ this.#wait = createWaitUntil();
695
+ this.waitUntil = this.#wait.waitUntil;
692
696
  const tls = resolveTLSOptions(this.options);
693
697
  const { port, hostname: host } = resolvePortAndHost(this.options);
694
698
  this.serveOptions = {
@@ -711,10 +715,7 @@ var NodeServer = class {
711
715
  else throw new Error("node.http2 option requires tls certificate!");
712
716
  else if (this.#isSecure) server = nodeHTTPS.createServer(this.serveOptions, handler);
713
717
  else server = nodeHTTP.createServer(this.serveOptions, handler);
714
- this.node = {
715
- server,
716
- handler
717
- };
718
+ this.node.server = server;
718
719
  if (!options.manual) this.serve();
719
720
  }
720
721
  serve() {
package/dist/cli.d.mts CHANGED
@@ -1,10 +1,6 @@
1
1
  import { LoadOptions } from "./loader.mjs";
2
- import { Server } from "srvx";
3
2
 
4
3
  //#region src/cli/types.d.ts
5
- declare global {
6
- var __srvx__: Server | undefined;
7
- }
8
4
  type MainOptions = CLIOptions & {
9
5
  args?: string[];
10
6
  meta?: {
package/dist/cli.mjs CHANGED
@@ -10,9 +10,13 @@ const NO_ENTRY_ERROR = "No server entry or public directory found";
10
10
  async function cliServe(cliOpts) {
11
11
  try {
12
12
  if (!process.env.NODE_ENV) process.env.NODE_ENV = cliOpts.prod ? "production" : "development";
13
+ let server;
13
14
  const loaded = await loadServerEntry({
14
15
  entry: cliOpts.entry,
15
- dir: cliOpts.dir
16
+ dir: cliOpts.dir,
17
+ get srvxServer() {
18
+ return server;
19
+ }
16
20
  });
17
21
  const { serve: srvxServe } = loaded.nodeCompat ? await import("srvx/node") : await import("srvx");
18
22
  const { serveStatic } = await import("srvx/static");
@@ -29,7 +33,7 @@ async function cliServe(cliOpts) {
29
33
  ...loaded.module
30
34
  };
31
35
  printInfo(cliOpts, loaded);
32
- await (globalThis.__srvx__ = srvxServe({
36
+ server = srvxServe({
33
37
  ...serverOptions,
34
38
  gracefulShutdown: !!cliOpts.prod,
35
39
  port: cliOpts.port ?? serverOptions.port,
@@ -48,7 +52,8 @@ async function cliServe(cliOpts) {
48
52
  cliOpts.static ? serveStatic({ dir: cliOpts.static }) : void 0,
49
53
  ...serverOptions.middleware || []
50
54
  ].filter(Boolean)
51
- })).ready();
55
+ });
56
+ await server.ready();
52
57
  } catch (error) {
53
58
  console.error(error);
54
59
  process.exit(1);
@@ -174,7 +179,7 @@ function getResponseFormat(res) {
174
179
  }
175
180
  const srvxMeta = {
176
181
  name: "srvx",
177
- version: "0.11.6",
182
+ version: "0.11.7",
178
183
  description: "Universal Server."
179
184
  };
180
185
  function usage(mainOpts) {
package/dist/loader.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { ServerHandler } from "srvx";
1
+ import { Server, ServerHandler } from "srvx";
2
2
 
3
3
  //#region src/loader.d.ts
4
4
  declare const defaultExts: string[];
@@ -30,6 +30,14 @@ type LoadOptions = {
30
30
  */
31
31
  nodeCompat?: boolean;
32
32
  /**
33
+ * Node.js server instance to return when intercepting `http.Server.listen`.
34
+ */
35
+ nodeServer?: NodeServer;
36
+ /**
37
+ * srvx server instance to return when intercepting `http.Server.listen`.
38
+ */
39
+ srvxServer?: Server;
40
+ /**
33
41
  * Hook called after the module is loaded to allow for custom processing.
34
42
  *
35
43
  * You can return a modified version of the module if needed.
@@ -68,7 +76,12 @@ type LoadedServerEntry = {
68
76
  * When `true`, no valid entry point could be located.
69
77
  */
70
78
  notFound?: boolean;
79
+ /**
80
+ * The original srvx server instance if the module used the loader API to export a server directly.
81
+ */
82
+ srvxServer?: Server;
71
83
  };
72
84
  declare function loadServerEntry(opts: LoadOptions): Promise<LoadedServerEntry>;
85
+ type NodeServer = NonNullable<Server["node"]>["server"];
73
86
  //#endregion
74
87
  export { LoadOptions, LoadedServerEntry, defaultEntries, defaultExts, loadServerEntry };
package/dist/loader.mjs CHANGED
@@ -2,6 +2,7 @@ import { pathToFileURL } from "node:url";
2
2
  import { existsSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
4
  import * as nodeHTTP$1 from "node:http";
5
+ import { EventEmitter } from "node:events";
5
6
  const defaultExts = [
6
7
  ".mjs",
7
8
  ".js",
@@ -35,13 +36,13 @@ async function loadServerEntry(opts) {
35
36
  const url = entry.startsWith("file://") ? entry : pathToFileURL(resolve(entry)).href;
36
37
  let mod;
37
38
  let interceptedNodeHandler;
38
- let interceptedFetchHandler;
39
+ let interceptedServer;
39
40
  try {
40
41
  if (opts.interceptHttpListen !== false) {
41
- const loaded = await interceptListen(() => import(url));
42
+ const loaded = await interceptListen(() => import(url), opts);
42
43
  mod = loaded.res;
43
44
  interceptedNodeHandler = loaded.listenHandler;
44
- interceptedFetchHandler = loaded.fetchHandler;
45
+ interceptedServer = loaded.server;
45
46
  } else mod = await import(url);
46
47
  } catch (error) {
47
48
  if (error?.code === "ERR_UNKNOWN_FILE_EXTENSION") {
@@ -52,7 +53,7 @@ async function loadServerEntry(opts) {
52
53
  throw error;
53
54
  }
54
55
  mod = await opts?.onLoad?.(mod) || mod;
55
- let fetchHandler = mod?.fetch || mod?.default?.fetch || mod?.default?.default?.fetch || interceptedFetchHandler;
56
+ let fetchHandler = mod?.fetch || mod?.default?.fetch || mod?.default?.default?.fetch || interceptedServer?.fetch;
56
57
  if (!fetchHandler && typeof mod?.default === "function" && mod.default.length < 2) fetchHandler = mod.default;
57
58
  let nodeCompat = false;
58
59
  if (!fetchHandler && opts.nodeCompat !== false) {
@@ -67,18 +68,21 @@ async function loadServerEntry(opts) {
67
68
  module: mod,
68
69
  nodeCompat,
69
70
  url,
70
- fetch: fetchHandler
71
+ fetch: fetchHandler,
72
+ srvxServer: interceptedServer
71
73
  };
72
74
  }
73
75
  let _interceptQueue = Promise.resolve();
74
- async function interceptListen(cb) {
76
+ async function interceptListen(cb, opts = {}) {
75
77
  const result = _interceptQueue.then(async () => {
76
78
  const originalListen = nodeHTTP$1.Server.prototype.listen;
77
79
  let res;
78
80
  let listenHandler;
79
- let fetchHandler;
80
- globalThis.__srvxLoader__ = (handler) => {
81
- fetchHandler = handler;
81
+ let server;
82
+ const nodeServerStub = opts.nodeServer || opts.srvxServer?.node?.server || new StubNodeServer(() => opts.srvxServer?.node?.server);
83
+ globalThis.__srvxLoader__ = (obj) => {
84
+ server = obj.server;
85
+ if (server && server.node) server.node.server ||= nodeServerStub;
82
86
  };
83
87
  try {
84
88
  nodeHTTP$1.Server.prototype.listen = function(arg1, arg2) {
@@ -89,15 +93,7 @@ async function interceptListen(cb) {
89
93
  setImmediate(() => {
90
94
  listenCallback?.();
91
95
  });
92
- return new Proxy({}, { get(_, prop) {
93
- const server = globalThis.__srvx__;
94
- if (!server && prop === "address") return () => ({
95
- address: "",
96
- family: "",
97
- port: 0
98
- });
99
- return server?.node?.server?.[prop];
100
- } });
96
+ return nodeServerStub;
101
97
  };
102
98
  res = await cb();
103
99
  } finally {
@@ -107,10 +103,36 @@ async function interceptListen(cb) {
107
103
  return {
108
104
  res,
109
105
  listenHandler,
110
- fetchHandler
106
+ server
111
107
  };
112
108
  });
113
109
  _interceptQueue = result.catch(() => {});
114
110
  return result;
115
111
  }
112
+ var StubNodeServer = class extends EventEmitter {
113
+ constructor(getServer) {
114
+ super();
115
+ return new Proxy(this, { get(target, prop, receiver) {
116
+ const server = getServer();
117
+ if (!server) return Reflect.get(target, prop, receiver);
118
+ const value = server[prop];
119
+ if (typeof value === "function") return value.bind(server);
120
+ return value;
121
+ } });
122
+ }
123
+ address() {
124
+ return {
125
+ address: "",
126
+ family: "",
127
+ port: 0
128
+ };
129
+ }
130
+ listen() {
131
+ return this;
132
+ }
133
+ close(callback) {
134
+ callback?.();
135
+ return this;
136
+ }
137
+ };
116
138
  export { defaultEntries, defaultExts, loadServerEntry };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "srvx",
3
- "version": "0.11.6",
3
+ "version": "0.11.7",
4
4
  "description": "Universal Server.",
5
5
  "homepage": "https://srvx.h3.dev",
6
6
  "license": "MIT",