srvx 0.2.0 → 0.2.2

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.
@@ -1,17 +1,23 @@
1
- import { ServerOptions, Server } from '../types.mjs';
1
+ import { ServerOptions, Server, BunFetchandler } from '../types.mjs';
2
2
  import * as Bun from 'bun';
3
3
  import 'node:http';
4
4
  import 'node:net';
5
5
  import '@cloudflare/workers-types';
6
6
 
7
- type BunHandler = (request: Request, server?: Bun.Server) => Response | Promise<Response>;
7
+ declare const Response: {
8
+ new (body?: BodyInit | null, init?: ResponseInit): Response;
9
+ prototype: Response;
10
+ error(): Response;
11
+ json(data: any, init?: ResponseInit): Response;
12
+ redirect(url: string | URL, status?: number): Response;
13
+ };
8
14
  declare function serve(options: ServerOptions): BunServer;
9
- declare class BunServer implements Server<BunHandler> {
15
+ declare class BunServer implements Server<BunFetchandler> {
10
16
  readonly runtime = "bun";
11
17
  readonly options: ServerOptions;
12
18
  readonly bun: Server["bun"];
13
19
  readonly serveOptions: Bun.ServeOptions;
14
- readonly fetch: BunHandler;
20
+ readonly fetch: BunFetchandler;
15
21
  constructor(options: ServerOptions);
16
22
  serve(): Promise<Awaited<this>>;
17
23
  get url(): string | undefined;
@@ -19,4 +25,4 @@ declare class BunServer implements Server<BunHandler> {
19
25
  close(closeAll?: boolean): Promise<void | undefined>;
20
26
  }
21
27
 
22
- export { serve };
28
+ export { Response, serve };
@@ -1,6 +1,7 @@
1
1
  import { r as resolvePort } from '../shared/srvx.PbkQy9Ck.mjs';
2
2
  import { w as wrapFetch } from '../shared/srvx.DhN4g5wJ.mjs';
3
3
 
4
+ const Response = globalThis.Response;
4
5
  function serve(options) {
5
6
  return new BunServer(options);
6
7
  }
@@ -48,4 +49,4 @@ class BunServer {
48
49
  }
49
50
  }
50
51
 
51
- export { serve };
52
+ export { Response, serve };
@@ -4,6 +4,13 @@ import 'node:http';
4
4
  import 'node:net';
5
5
  import 'bun';
6
6
 
7
+ declare const Response: {
8
+ new (body?: BodyInit | null, init?: ResponseInit): Response;
9
+ prototype: Response;
10
+ error(): Response;
11
+ json(data: any, init?: ResponseInit): Response;
12
+ redirect(url: string | URL, status?: number): Response;
13
+ };
7
14
  declare function serve(options: ServerOptions): Server<CF.ExportedHandlerFetchHandler>;
8
15
 
9
- export { serve };
16
+ export { Response, serve };
@@ -1,5 +1,6 @@
1
1
  import { w as wrapFetch } from '../shared/srvx.DhN4g5wJ.mjs';
2
2
 
3
+ const Response = globalThis.Response;
3
4
  function serve(options) {
4
5
  return new CloudflareServer(options);
5
6
  }
@@ -41,4 +42,4 @@ class CloudflareServer {
41
42
  }
42
43
  }
43
44
 
44
- export { serve };
45
+ export { Response, serve };
@@ -1,18 +1,24 @@
1
- import { ServerOptions, Server } from '../types.mjs';
1
+ import { ServerOptions, Server, DenoFetchHandler } from '../types.mjs';
2
2
  import 'node:http';
3
3
  import 'node:net';
4
4
  import 'bun';
5
5
  import '@cloudflare/workers-types';
6
6
 
7
- type DenoHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.NetAddr>) => Response | Promise<Response>;
7
+ declare const Response: {
8
+ new (body?: BodyInit | null, init?: ResponseInit): Response;
9
+ prototype: Response;
10
+ error(): Response;
11
+ json(data: any, init?: ResponseInit): Response;
12
+ redirect(url: string | URL, status?: number): Response;
13
+ };
8
14
  declare function serve(options: ServerOptions): DenoServer;
9
- declare class DenoServer implements Server<DenoHandler> {
15
+ declare class DenoServer implements Server<DenoFetchHandler> {
10
16
  #private;
11
17
  readonly runtime = "deno";
12
18
  readonly options: ServerOptions;
13
19
  readonly deno: Server["deno"];
14
20
  readonly serveOptions: Deno.ServeTcpOptions;
15
- readonly fetch: DenoHandler;
21
+ readonly fetch: DenoFetchHandler;
16
22
  constructor(options: ServerOptions);
17
23
  serve(): Promise<this>;
18
24
  get url(): string | undefined;
@@ -20,4 +26,4 @@ declare class DenoServer implements Server<DenoHandler> {
20
26
  close(): Promise<void | undefined>;
21
27
  }
22
28
 
23
- export { serve };
29
+ export { Response, serve };
@@ -1,6 +1,7 @@
1
1
  import { r as resolvePort, f as fmtURL } from '../shared/srvx.PbkQy9Ck.mjs';
2
2
  import { w as wrapFetch } from '../shared/srvx.DhN4g5wJ.mjs';
3
3
 
4
+ const Response = globalThis.Response;
4
5
  function serve(options) {
5
6
  return new DenoServer(options);
6
7
  }
@@ -64,4 +65,4 @@ class DenoServer {
64
65
  }
65
66
  }
66
67
 
67
- export { serve };
68
+ export { Response, serve };
@@ -1,5 +1,6 @@
1
- import { ServerOptions, Server } from '../types.mjs';
1
+ import { ServerOptions, Server, FetchHandler, NodeHttpHandler } from '../types.mjs';
2
2
  import NodeHttp__default from 'node:http';
3
+ import { Readable } from 'node:stream';
3
4
  import 'node:net';
4
5
  import 'bun';
5
6
  import '@cloudflare/workers-types';
@@ -7,8 +8,8 @@ import '@cloudflare/workers-types';
7
8
  type NodeFastResponse = InstanceType<typeof NodeFastResponse>;
8
9
  declare const NodeFastResponse: {
9
10
  new (body?: BodyInit | null, init?: ResponseInit): {
10
- "__#4112@#body"?: BodyInit | null;
11
- "__#4112@#init"?: ResponseInit;
11
+ "__#4201@#body"?: BodyInit | null;
12
+ "__#4201@#init"?: ResponseInit;
12
13
  /**
13
14
  * Prepare Node.js response object
14
15
  */
@@ -16,14 +17,14 @@ declare const NodeFastResponse: {
16
17
  status: number;
17
18
  statusText: string;
18
19
  headers: NodeHttp__default.OutgoingHttpHeader[];
19
- body: string | Uint8Array<ArrayBufferLike> | ReadableStream<Uint8Array<ArrayBufferLike>> | Buffer<ArrayBufferLike> | DataView<ArrayBufferLike> | null | undefined;
20
+ body: string | Uint8Array<ArrayBufferLike> | ReadableStream<Uint8Array<ArrayBufferLike>> | Readable | Buffer<ArrayBufferLike> | DataView<ArrayBufferLike> | null | undefined;
20
21
  };
21
22
  /** Lazy initialized response instance */
22
- "__#4112@#responseObj"?: Response;
23
+ "__#4201@#responseObj"?: Response;
23
24
  /** Lazy initialized headers instance */
24
- "__#4112@#headersObj"?: Headers;
25
+ "__#4201@#headersObj"?: Headers;
25
26
  clone(): Response;
26
- readonly "__#4112@#response": Response;
27
+ readonly "__#4201@#response": Response;
27
28
  readonly headers: Headers;
28
29
  readonly ok: boolean;
29
30
  readonly redirected: boolean;
@@ -31,7 +32,7 @@ declare const NodeFastResponse: {
31
32
  readonly statusText: string;
32
33
  readonly type: ResponseType;
33
34
  readonly url: string;
34
- "__#4112@#fastBody"<T extends object>(as: new (...args: any[]) => T): T | null | false;
35
+ "__#4201@#fastBody"<T extends object>(as: new (...args: any[]) => T): T | null | false;
35
36
  readonly body: ReadableStream<Uint8Array> | null;
36
37
  readonly bodyUsed: boolean;
37
38
  arrayBuffer(): Promise<ArrayBuffer>;
@@ -44,5 +45,6 @@ declare const NodeFastResponse: {
44
45
  };
45
46
 
46
47
  declare function serve(options: ServerOptions): Server;
48
+ declare function toNodeHandler(fetchHandler: FetchHandler): NodeHttpHandler;
47
49
 
48
- export { NodeFastResponse as Response, serve };
50
+ export { NodeFastResponse as Response, serve, toNodeHandler };
@@ -10,11 +10,18 @@ async function sendNodeResponse(nodeRes, webRes) {
10
10
  }
11
11
  if (webRes.nodeResponse) {
12
12
  const res = webRes.nodeResponse();
13
- nodeRes.writeHead(res.status, res.statusText, res.headers);
14
- if (res.body instanceof ReadableStream) {
15
- return streamBody(res.body, nodeRes);
13
+ if (!nodeRes.headersSent) {
14
+ nodeRes.writeHead(res.status, res.statusText, res.headers);
15
+ }
16
+ if (res.body) {
17
+ if (res.body instanceof ReadableStream) {
18
+ return streamBody(res.body, nodeRes);
19
+ } else if (typeof res.body?.pipe === "function") {
20
+ res.body.pipe(nodeRes);
21
+ return new Promise((resolve) => nodeRes.on("close", resolve));
22
+ }
23
+ nodeRes.write(res.body);
16
24
  }
17
- nodeRes.write(res.body);
18
25
  return endNodeResponse(nodeRes);
19
26
  }
20
27
  const headerEntries = [];
@@ -27,7 +34,9 @@ async function sendNodeResponse(nodeRes, webRes) {
27
34
  headerEntries.push([key, value]);
28
35
  }
29
36
  }
30
- nodeRes.writeHead(webRes.status || 200, webRes.statusText, headerEntries);
37
+ if (!nodeRes.headersSent) {
38
+ nodeRes.writeHead(webRes.status || 200, webRes.statusText, headerEntries);
39
+ }
31
40
  return webRes.body ? streamBody(webRes.body, nodeRes) : endNodeResponse(nodeRes);
32
41
  }
33
42
  function endNodeResponse(nodeRes) {
@@ -516,12 +525,10 @@ const NodeFastResponse = /* @__PURE__ */ (() => (
516
525
  const status = this.#init?.status ?? 200;
517
526
  const statusText = this.#init?.statusText ?? "";
518
527
  const headers = [];
519
- let headersInit = this.#init?.headers;
528
+ const headersInit = this.#init?.headers;
520
529
  if (headersInit) {
521
- if (typeof headersInit === "object") {
522
- headersInit = Object.entries(headersInit);
523
- }
524
- for (const [key, value] of headersInit) {
530
+ const headerEntries = headersInit.entries ? headersInit.entries() : Object.entries(headersInit);
531
+ for (const [key, value] of headerEntries) {
525
532
  if (key === "set-cookie") {
526
533
  for (const setCookie of splitSetCookieString(value)) {
527
534
  headers.push(["set-cookie", setCookie]);
@@ -549,6 +556,8 @@ const NodeFastResponse = /* @__PURE__ */ (() => (
549
556
  if (bodyInit.type) {
550
557
  headers.push(["content-type", bodyInit.type]);
551
558
  }
559
+ } else if (typeof bodyInit.pipe === "function") {
560
+ body = bodyInit;
552
561
  } else {
553
562
  const res = new Response(bodyInit);
554
563
  body = res.body;
@@ -724,6 +733,14 @@ const NodeFastResponse = /* @__PURE__ */ (() => (
724
733
  function serve(options) {
725
734
  return new NodeServer(options);
726
735
  }
736
+ function toNodeHandler(fetchHandler) {
737
+ return (nodeReq, nodeRes) => {
738
+ const request = new NodeRequestProxy(nodeReq);
739
+ request.node = { req: nodeReq, res: nodeRes };
740
+ const res = fetchHandler(request);
741
+ return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
742
+ };
743
+ }
727
744
  class NodeServer {
728
745
  constructor(options) {
729
746
  this.runtime = "node";
@@ -779,4 +796,4 @@ class NodeServer {
779
796
  }
780
797
  }
781
798
 
782
- export { NodeFastResponse as Response, serve };
799
+ export { NodeFastResponse as Response, serve, toNodeHandler };
package/dist/types.d.mts CHANGED
@@ -4,6 +4,7 @@ import * as Bun from 'bun';
4
4
  import * as CF from '@cloudflare/workers-types';
5
5
 
6
6
  type MaybePromise<T> = T | Promise<T>;
7
+ declare const Response: globalThis.Response;
7
8
  /**
8
9
  * Create a new server instance.
9
10
  */
@@ -166,5 +167,10 @@ interface ServerRequest extends Request {
166
167
  context: CF.ExecutionContext;
167
168
  };
168
169
  }
170
+ type FetchHandler = (request: Request) => Response | Promise<Response>;
171
+ type BunFetchandler = (request: Request, server?: Bun.Server) => Response | Promise<Response>;
172
+ type DenoFetchHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.NetAddr>) => Response | Promise<Response>;
173
+ type NodeHttpHandler = (nodeReq: NodeHttp.IncomingMessage, nodeRes: NodeHttp.ServerResponse) => void | Promise<void>;
174
+ type CloudflareFetchHandler = CF.ExportedHandlerFetchHandler;
169
175
 
170
- export { type Server, type ServerHandler, type ServerOptions, type ServerPlugin, type ServerPluginInstance, type ServerRequest, serve };
176
+ export { type BunFetchandler, type CloudflareFetchHandler, type DenoFetchHandler, type FetchHandler, type NodeHttpHandler, Response, type Server, type ServerHandler, type ServerOptions, type ServerPlugin, type ServerPluginInstance, type ServerRequest, serve };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "srvx",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Universal Server API based on web platform standards. Works seamlessly with Deno, Bun and Node.js.",
5
5
  "repository": "unjs/srvx",
6
6
  "license": "MIT",