srvx 0.2.7 → 0.3.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.
@@ -13,11 +13,14 @@ class BunServer {
13
13
  this.options = options;
14
14
  const fetchHandler = wrapFetch(this, this.options.fetch);
15
15
  this.fetch = (request, server) => {
16
- Object.defineProperties(request, {
17
- bun: { value: { server }, enumerable: true },
18
- remoteAddress: {
19
- get: () => server?.requestIP(request)?.address,
20
- enumerable: true
16
+ Object.defineProperty(request, "x", {
17
+ enumerable: true,
18
+ value: {
19
+ runtime: "bun",
20
+ bun: { server },
21
+ get ip() {
22
+ return server?.requestIP(request)?.address;
23
+ }
21
24
  }
22
25
  });
23
26
  return fetchHandler(request);
@@ -13,11 +13,11 @@ class CloudflareServer {
13
13
  this.options.fetch
14
14
  );
15
15
  this.fetch = (request, env, context) => {
16
- Object.defineProperties(request, {
17
- cloudflare: { value: { env, context }, enumerable: true },
18
- remoteAddress: {
19
- get: () => void 0,
20
- enumerable: true
16
+ Object.defineProperty(request, "x", {
17
+ enumerable: true,
18
+ value: {
19
+ runtime: "cloudflare",
20
+ cloudflare: { env, context }
21
21
  }
22
22
  });
23
23
  return fetchHandler(request);
@@ -13,11 +13,14 @@ class DenoServer {
13
13
  this.options = options;
14
14
  const fetchHandler = wrapFetch(this, this.options.fetch);
15
15
  this.fetch = (request, info) => {
16
- Object.defineProperties(request, {
17
- deno: { value: { info, server: this.deno?.server }, enumerable: true },
18
- remoteAddress: {
19
- get: () => info?.remoteAddr?.hostname,
20
- enumerable: true
16
+ Object.defineProperty(request, "x", {
17
+ enumerable: true,
18
+ value: {
19
+ runtime: "deno",
20
+ deno: { info, server: this.deno?.server },
21
+ get ip() {
22
+ return info?.remoteAddr?.hostname;
23
+ }
21
24
  }
22
25
  });
23
26
  return fetchHandler(request);
@@ -1,4 +1,4 @@
1
- import { ServerOptions, Server, FetchHandler, NodeHttpHandler } from '../types.mjs';
1
+ import { ServerRequest, ServerOptions, Server, FetchHandler, NodeHttpHandler } from '../types.mjs';
2
2
  import NodeHttp__default from 'node:http';
3
3
  import { Readable } from 'node:stream';
4
4
  import 'node:https';
@@ -6,16 +6,16 @@ import 'node:net';
6
6
  import 'bun';
7
7
  import '@cloudflare/workers-types';
8
8
 
9
- type NodeFastResponse = InstanceType<typeof NodeFastResponse>;
9
+ type NodeResponse = InstanceType<typeof NodeResponse>;
10
10
  /**
11
11
  * Fast Response for Node.js runtime
12
12
  *
13
13
  * It is faster because in most cases it doesn't create a full Response instance.
14
14
  */
15
- declare const NodeFastResponse: {
15
+ declare const NodeResponse: {
16
16
  new (body?: BodyInit | null, init?: ResponseInit): {
17
- "__#4363@#body"?: BodyInit | null;
18
- "__#4363@#init"?: ResponseInit;
17
+ "__#4362@#body"?: BodyInit | null;
18
+ "__#4362@#init"?: ResponseInit;
19
19
  /**
20
20
  * Prepare Node.js response object
21
21
  */
@@ -26,11 +26,11 @@ declare const NodeFastResponse: {
26
26
  body: string | Uint8Array<ArrayBufferLike> | ReadableStream<Uint8Array<ArrayBufferLike>> | Readable | Buffer<ArrayBufferLike> | DataView<ArrayBufferLike> | null | undefined;
27
27
  };
28
28
  /** Lazy initialized response instance */
29
- "__#4363@#responseObj"?: globalThis.Response;
29
+ "__#4362@#responseObj"?: globalThis.Response;
30
30
  /** Lazy initialized headers instance */
31
- "__#4363@#headersObj"?: Headers;
31
+ "__#4362@#headersObj"?: Headers;
32
32
  clone(): globalThis.Response;
33
- readonly "__#4363@#response": globalThis.Response;
33
+ readonly "__#4362@#response": globalThis.Response;
34
34
  readonly headers: Headers;
35
35
  readonly ok: boolean;
36
36
  readonly redirected: boolean;
@@ -38,7 +38,7 @@ declare const NodeFastResponse: {
38
38
  readonly statusText: string;
39
39
  readonly type: ResponseType;
40
40
  readonly url: string;
41
- "__#4363@#fastBody"<T extends object>(as: new (...args: any[]) => T): T | null | false;
41
+ "__#4362@#fastBody"<T extends object>(as: new (...args: any[]) => T): T | null | false;
42
42
  readonly body: ReadableStream<Uint8Array> | null;
43
43
  readonly bodyUsed: boolean;
44
44
  arrayBuffer(): Promise<ArrayBuffer>;
@@ -48,9 +48,80 @@ declare const NodeFastResponse: {
48
48
  text(): Promise<string>;
49
49
  json(): Promise<any>;
50
50
  };
51
+ json(data: any, init?: ResponseInit): globalThis.Response;
52
+ error(): globalThis.Response;
53
+ redirect(url: string | URL, status?: number): globalThis.Response;
54
+ };
55
+
56
+ declare const NodeRequest: {
57
+ new (nodeCtx: {
58
+ req: NodeHttp__default.IncomingMessage;
59
+ res: NodeHttp__default.ServerResponse;
60
+ }): ServerRequest;
61
+ };
62
+
63
+ declare const kNodeInspect: unique symbol;
64
+
65
+ declare const NodeRequestHeaders: {
66
+ new (nodeCtx: {
67
+ req: NodeHttp__default.IncomingMessage;
68
+ res?: NodeHttp__default.ServerResponse;
69
+ }): {
70
+ _node: {
71
+ req: NodeHttp__default.IncomingMessage;
72
+ res?: NodeHttp__default.ServerResponse;
73
+ };
74
+ append(name: string, value: string): void;
75
+ delete(name: string): void;
76
+ get(name: string): string | null;
77
+ getSetCookie(): string[];
78
+ has(name: string): boolean;
79
+ set(name: string, value: string): void;
80
+ readonly count: number;
81
+ getAll(_name: "set-cookie" | "Set-Cookie"): string[];
82
+ toJSON(): Record<string, string>;
83
+ forEach(cb: (value: string, key: string, parent: /*elided*/ any) => void, thisArg?: any): void;
84
+ entries(): HeadersIterator<[string, string]>;
85
+ keys(): HeadersIterator<string>;
86
+ values(): HeadersIterator<string>;
87
+ [Symbol.iterator](): HeadersIterator<[string, string]>;
88
+ readonly [Symbol.toStringTag]: string;
89
+ [kNodeInspect](): {
90
+ [k: string]: string;
91
+ };
92
+ };
93
+ };
94
+ declare const NodeResponseHeaders: {
95
+ new (nodeCtx: {
96
+ req?: NodeHttp__default.IncomingMessage;
97
+ res: NodeHttp__default.ServerResponse;
98
+ }): {
99
+ _node: {
100
+ req?: NodeHttp__default.IncomingMessage;
101
+ res: NodeHttp__default.ServerResponse;
102
+ };
103
+ append(name: string, value: string): void;
104
+ delete(name: string): void;
105
+ get(name: string): string | null;
106
+ getSetCookie(): string[];
107
+ has(name: string): boolean;
108
+ set(name: string, value: string): void;
109
+ readonly count: number;
110
+ getAll(_name: "set-cookie" | "Set-Cookie"): string[];
111
+ toJSON(): Record<string, string>;
112
+ forEach(cb: (value: string, key: string, parent: /*elided*/ any) => void, thisArg?: any): void;
113
+ entries(): HeadersIterator<[string, string]>;
114
+ keys(): HeadersIterator<string>;
115
+ values(): HeadersIterator<string>;
116
+ [Symbol.iterator](): HeadersIterator<[string, string]>;
117
+ readonly [Symbol.toStringTag]: string;
118
+ [kNodeInspect](): {
119
+ [k: string]: string;
120
+ };
121
+ };
51
122
  };
52
123
 
53
124
  declare function serve(options: ServerOptions): Server;
54
125
  declare function toNodeHandler(fetchHandler: FetchHandler): NodeHttpHandler;
55
126
 
56
- export { NodeFastResponse as Response, serve, toNodeHandler };
127
+ export { NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, NodeRequest as Request, NodeResponse as Response, serve, toNodeHandler };
@@ -93,14 +93,14 @@ const kNodeInspect = /* @__PURE__ */ Symbol.for(
93
93
  "nodejs.util.inspect.custom"
94
94
  );
95
95
 
96
- const NodeReqHeadersProxy = /* @__PURE__ */ (() => {
96
+ const NodeRequestHeaders = /* @__PURE__ */ (() => {
97
97
  const _Headers = class Headers {
98
98
  constructor(nodeCtx) {
99
- this.node = nodeCtx;
99
+ this._node = nodeCtx;
100
100
  }
101
101
  append(name, value) {
102
102
  name = name.toLowerCase();
103
- const _headers = this.node.req.headers;
103
+ const _headers = this._node.req.headers;
104
104
  const _current = _headers[name];
105
105
  if (_current) {
106
106
  if (Array.isArray(_current)) {
@@ -114,14 +114,18 @@ const NodeReqHeadersProxy = /* @__PURE__ */ (() => {
114
114
  }
115
115
  delete(name) {
116
116
  name = name.toLowerCase();
117
- this.node.req.headers[name] = void 0;
117
+ this._node.req.headers[name] = void 0;
118
118
  }
119
119
  get(name) {
120
120
  name = name.toLowerCase();
121
- return _normalizeValue(this.node.req.headers[name]);
121
+ const rawValue = this._node.req.headers[name];
122
+ if (rawValue === void 0) {
123
+ return null;
124
+ }
125
+ return _normalizeValue(this._node.req.headers[name]);
122
126
  }
123
127
  getSetCookie() {
124
- const setCookie = this.node.req.headers["set-cookie"];
128
+ const setCookie = this._node.req.headers["set-cookie"];
125
129
  if (!setCookie || setCookie.length === 0) {
126
130
  return [];
127
131
  }
@@ -129,11 +133,11 @@ const NodeReqHeadersProxy = /* @__PURE__ */ (() => {
129
133
  }
130
134
  has(name) {
131
135
  name = name.toLowerCase();
132
- return !!this.node.req.headers[name];
136
+ return !!this._node.req.headers[name];
133
137
  }
134
138
  set(name, value) {
135
139
  name = name.toLowerCase();
136
- this.node.req.headers[name] = value;
140
+ this._node.req.headers[name] = value;
137
141
  }
138
142
  get count() {
139
143
  throw new Error("Method not implemented.");
@@ -142,7 +146,7 @@ const NodeReqHeadersProxy = /* @__PURE__ */ (() => {
142
146
  throw new Error("Method not implemented.");
143
147
  }
144
148
  toJSON() {
145
- const _headers = this.node.req.headers;
149
+ const _headers = this._node.req.headers;
146
150
  const result = {};
147
151
  for (const key in _headers) {
148
152
  if (_headers[key]) {
@@ -152,7 +156,7 @@ const NodeReqHeadersProxy = /* @__PURE__ */ (() => {
152
156
  return result;
153
157
  }
154
158
  forEach(cb, thisArg) {
155
- const _headers = this.node.req.headers;
159
+ const _headers = this._node.req.headers;
156
160
  for (const key in _headers) {
157
161
  if (_headers[key]) {
158
162
  cb.call(
@@ -165,19 +169,110 @@ const NodeReqHeadersProxy = /* @__PURE__ */ (() => {
165
169
  }
166
170
  }
167
171
  *entries() {
168
- const _headers = this.node.req.headers;
172
+ const _headers = this._node.req.headers;
169
173
  for (const key in _headers) {
170
174
  yield [key, _normalizeValue(_headers[key])];
171
175
  }
172
176
  }
173
177
  *keys() {
174
- const keys = Object.keys(this.node.req.headers);
178
+ const keys = Object.keys(this._node.req.headers);
175
179
  for (const key of keys) {
176
180
  yield key;
177
181
  }
178
182
  }
179
183
  *values() {
180
- const values = Object.values(this.node.req.headers);
184
+ const values = Object.values(this._node.req.headers);
185
+ for (const value of values) {
186
+ yield _normalizeValue(value);
187
+ }
188
+ }
189
+ [Symbol.iterator]() {
190
+ return this.entries()[Symbol.iterator]();
191
+ }
192
+ get [Symbol.toStringTag]() {
193
+ return "Headers";
194
+ }
195
+ [kNodeInspect]() {
196
+ return Object.fromEntries(this.entries());
197
+ }
198
+ };
199
+ Object.setPrototypeOf(_Headers.prototype, globalThis.Headers.prototype);
200
+ return _Headers;
201
+ })();
202
+ const NodeResponseHeaders = /* @__PURE__ */ (() => {
203
+ const _Headers = class Headers {
204
+ constructor(nodeCtx) {
205
+ this._node = nodeCtx;
206
+ }
207
+ append(name, value) {
208
+ this._node.res.appendHeader(name, value);
209
+ }
210
+ delete(name) {
211
+ this._node.res.removeHeader(name);
212
+ }
213
+ get(name) {
214
+ const rawValue = this._node.res.getHeader(name);
215
+ if (rawValue === void 0) {
216
+ return null;
217
+ }
218
+ return _normalizeValue(rawValue);
219
+ }
220
+ getSetCookie() {
221
+ const setCookie = _normalizeValue(this._node.res.getHeader("set-cookie"));
222
+ if (!setCookie) {
223
+ return [];
224
+ }
225
+ return splitSetCookieString(setCookie);
226
+ }
227
+ has(name) {
228
+ return this._node.res.hasHeader(name);
229
+ }
230
+ set(name, value) {
231
+ this._node.res.setHeader(name, value);
232
+ }
233
+ get count() {
234
+ throw new Error("Method not implemented.");
235
+ }
236
+ getAll(_name) {
237
+ throw new Error("Method not implemented.");
238
+ }
239
+ toJSON() {
240
+ const _headers = this._node.res.getHeaders();
241
+ const result = {};
242
+ for (const key in _headers) {
243
+ if (_headers[key]) {
244
+ result[key] = _normalizeValue(_headers[key]);
245
+ }
246
+ }
247
+ return result;
248
+ }
249
+ forEach(cb, thisArg) {
250
+ const _headers = this._node.res.getHeaders();
251
+ for (const key in _headers) {
252
+ if (_headers[key]) {
253
+ cb.call(
254
+ thisArg,
255
+ _normalizeValue(_headers[key]),
256
+ key,
257
+ this
258
+ );
259
+ }
260
+ }
261
+ }
262
+ *entries() {
263
+ const _headers = this._node.res.getHeaders();
264
+ for (const key in _headers) {
265
+ yield [key, _normalizeValue(_headers[key])];
266
+ }
267
+ }
268
+ *keys() {
269
+ const keys = this._node.res.getHeaderNames();
270
+ for (const key of keys) {
271
+ yield key;
272
+ }
273
+ }
274
+ *values() {
275
+ const values = Object.values(this._node.res.getHeaders());
181
276
  for (const value of values) {
182
277
  yield _normalizeValue(value);
183
278
  }
@@ -199,16 +294,16 @@ function _normalizeValue(value) {
199
294
  if (Array.isArray(value)) {
200
295
  return value.join(", ");
201
296
  }
202
- return value || "";
297
+ return typeof value === "string" ? value : String(value ?? "");
203
298
  }
204
299
 
205
- const NodeReqURLProxy = /* @__PURE__ */ (() => {
300
+ const NodeRequestURL = /* @__PURE__ */ (() => {
206
301
  const _URL = class URL {
207
302
  constructor(nodeCtx) {
208
303
  this._hash = "";
209
304
  this._username = "";
210
305
  this._password = "";
211
- this.node = nodeCtx;
306
+ this._node = nodeCtx;
212
307
  }
213
308
  get hash() {
214
309
  return this._hash;
@@ -230,17 +325,17 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => {
230
325
  }
231
326
  // host
232
327
  get host() {
233
- return this.node.req.headers.host || "";
328
+ return this._node.req.headers.host || "";
234
329
  }
235
330
  set host(value) {
236
331
  this._hostname = void 0;
237
332
  this._port = void 0;
238
- this.node.req.headers.host = value;
333
+ this._node.req.headers.host = value;
239
334
  }
240
335
  // hostname
241
336
  get hostname() {
242
337
  if (this._hostname === void 0) {
243
- const [hostname, port] = parseHost(this.node.req.headers.host);
338
+ const [hostname, port] = parseHost(this._node.req.headers.host);
244
339
  if (this._port === void 0 && port) {
245
340
  this._port = String(Number.parseInt(port) || "");
246
341
  }
@@ -254,11 +349,11 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => {
254
349
  // port
255
350
  get port() {
256
351
  if (this._port === void 0) {
257
- const [hostname, port] = parseHost(this.node.req.headers.host);
352
+ const [hostname, port] = parseHost(this._node.req.headers.host);
258
353
  if (this._hostname === void 0 && hostname) {
259
354
  this._hostname = hostname;
260
355
  }
261
- this._port = port || String(this.node.req.socket?.localPort || "");
356
+ this._port = port || String(this._node.req.socket?.localPort || "");
262
357
  }
263
358
  return this._port;
264
359
  }
@@ -268,7 +363,7 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => {
268
363
  // pathname
269
364
  get pathname() {
270
365
  if (this._pathname === void 0) {
271
- const [pathname, search] = parsePath(this.node.req.url || "/");
366
+ const [pathname, search] = parsePath(this._node.req.url || "/");
272
367
  this._pathname = pathname;
273
368
  if (this._search === void 0) {
274
369
  this._search = search;
@@ -284,12 +379,12 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => {
284
379
  return;
285
380
  }
286
381
  this._pathname = value;
287
- this.node.req.url = value + this.search;
382
+ this._node.req.url = value + this.search;
288
383
  }
289
384
  // search
290
385
  get search() {
291
386
  if (this._search === void 0) {
292
- const [pathname, search] = parsePath(this.node.req.url || "/");
387
+ const [pathname, search] = parsePath(this._node.req.url || "/");
293
388
  this._search = search;
294
389
  if (this._pathname === void 0) {
295
390
  this._pathname = pathname;
@@ -308,7 +403,7 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => {
308
403
  }
309
404
  this._search = value;
310
405
  this._searchParams = void 0;
311
- this.node.req.url = this.pathname + value;
406
+ this._node.req.url = this.pathname + value;
312
407
  }
313
408
  // searchParams
314
409
  get searchParams() {
@@ -324,7 +419,7 @@ const NodeReqURLProxy = /* @__PURE__ */ (() => {
324
419
  // protocol
325
420
  get protocol() {
326
421
  if (!this._protocol) {
327
- this._protocol = this.node.req.socket?.encrypted || this.node.req.headers["x-forwarded-proto"] === "https" ? "https:" : "http:";
422
+ this._protocol = this._node.req.socket?.encrypted || this._node.req.headers["x-forwarded-proto"] === "https" ? "https:" : "http:";
328
423
  }
329
424
  return this._protocol;
330
425
  }
@@ -381,7 +476,7 @@ function parseHost(host) {
381
476
  return [s[0], String(Number.parseInt(s[1]) || "")];
382
477
  }
383
478
 
384
- const NodeRequestProxy = /* @__PURE__ */ (() => {
479
+ const NodeRequest = /* @__PURE__ */ (() => {
385
480
  const _Request = class Request {
386
481
  #url;
387
482
  #headers;
@@ -395,23 +490,27 @@ const NodeRequestProxy = /* @__PURE__ */ (() => {
395
490
  #textBody;
396
491
  #bodyStream;
397
492
  constructor(nodeCtx) {
398
- this.node = nodeCtx;
493
+ this._node = nodeCtx;
494
+ this.x = {
495
+ runtime: "node",
496
+ node: nodeCtx,
497
+ get ip() {
498
+ return nodeCtx.req.socket?.remoteAddress;
499
+ }
500
+ };
399
501
  }
400
502
  get headers() {
401
503
  if (!this.#headers) {
402
- this.#headers = new NodeReqHeadersProxy(this.node);
504
+ this.#headers = new NodeRequestHeaders(this._node);
403
505
  }
404
506
  return this.#headers;
405
507
  }
406
- get remoteAddress() {
407
- return this.node.req.socket?.remoteAddress;
408
- }
409
508
  clone() {
410
- return new _Request({ ...this.node });
509
+ return new _Request({ ...this._node });
411
510
  }
412
511
  get _url() {
413
512
  if (!this.#url) {
414
- this.#url = new NodeReqURLProxy(this.node);
513
+ this.#url = new NodeRequestURL(this._node);
415
514
  }
416
515
  return this.#url;
417
516
  }
@@ -419,7 +518,7 @@ const NodeRequestProxy = /* @__PURE__ */ (() => {
419
518
  return this._url.href;
420
519
  }
421
520
  get method() {
422
- return this.node.req.method || "GET";
521
+ return this._node.req.method || "GET";
423
522
  }
424
523
  get signal() {
425
524
  if (!this.#abortSignal) {
@@ -434,13 +533,13 @@ const NodeRequestProxy = /* @__PURE__ */ (() => {
434
533
  if (this.#hasBody !== void 0) {
435
534
  return this.#hasBody;
436
535
  }
437
- const method = this.node.req.method?.toUpperCase();
536
+ const method = this._node.req.method?.toUpperCase();
438
537
  if (!method || !(method === "PATCH" || method === "POST" || method === "PUT" || method === "DELETE")) {
439
538
  this.#hasBody = false;
440
539
  return false;
441
540
  }
442
- if (!Number.parseInt(this.node.req.headers["content-length"] || "")) {
443
- const isChunked = (this.node.req.headers["transfer-encoding"] || "").split(",").map((e) => e.trim()).filter(Boolean).includes("chunked");
541
+ if (!Number.parseInt(this._node.req.headers["content-length"] || "")) {
542
+ const isChunked = (this._node.req.headers["transfer-encoding"] || "").split(",").map((e) => e.trim()).filter(Boolean).includes("chunked");
444
543
  if (!isChunked) {
445
544
  this.#hasBody = false;
446
545
  return false;
@@ -457,7 +556,7 @@ const NodeRequestProxy = /* @__PURE__ */ (() => {
457
556
  this.#bodyUsed = true;
458
557
  this.#bodyStream = new ReadableStream({
459
558
  start: (controller) => {
460
- this.node.req.on("data", (chunk) => {
559
+ this._node.req.on("data", (chunk) => {
461
560
  controller.enqueue(chunk);
462
561
  }).once("error", (error) => {
463
562
  controller.error(error);
@@ -491,7 +590,7 @@ const NodeRequestProxy = /* @__PURE__ */ (() => {
491
590
  if (!this.#blobBody) {
492
591
  this.#blobBody = this.bytes().then((bytes) => {
493
592
  return new Blob([bytes], {
494
- type: this.node.req.headers["content-type"]
593
+ type: this._node.req.headers["content-type"]
495
594
  });
496
595
  });
497
596
  }
@@ -547,7 +646,10 @@ async function _readStream(stream) {
547
646
  return Buffer.concat(chunks);
548
647
  }
549
648
 
550
- const NodeFastResponse = /* @__PURE__ */ (() => {
649
+ const NodeResponse = /* @__PURE__ */ (() => {
650
+ const CONTENT_TYPE = "content-type";
651
+ const JSON_TYPE = "application/json";
652
+ const JSON_HEADER = [[CONTENT_TYPE, JSON_TYPE]];
551
653
  const _Response = class Response {
552
654
  #body;
553
655
  #init;
@@ -555,6 +657,27 @@ const NodeFastResponse = /* @__PURE__ */ (() => {
555
657
  this.#body = body;
556
658
  this.#init = init;
557
659
  }
660
+ static json(data, init) {
661
+ if (init?.headers) {
662
+ if (!init.headers[CONTENT_TYPE]) {
663
+ const initHeaders = new Headers(init.headers);
664
+ if (!initHeaders.has(CONTENT_TYPE)) {
665
+ initHeaders.set(CONTENT_TYPE, JSON_TYPE);
666
+ }
667
+ init = { ...init, headers: initHeaders };
668
+ }
669
+ } else {
670
+ init = init ? { ...init } : {};
671
+ init.headers = JSON_HEADER;
672
+ }
673
+ return new _Response(JSON.stringify(data), init);
674
+ }
675
+ static error() {
676
+ return globalThis.Response.error();
677
+ }
678
+ static redirect(url, status) {
679
+ return globalThis.Response.redirect(url, status);
680
+ }
558
681
  /**
559
682
  * Prepare Node.js response object
560
683
  */
@@ -774,7 +897,7 @@ function serve(options) {
774
897
  }
775
898
  function toNodeHandler(fetchHandler) {
776
899
  return (nodeReq, nodeRes) => {
777
- const request = new NodeRequestProxy({ req: nodeReq, res: nodeRes });
900
+ const request = new NodeRequest({ req: nodeReq, res: nodeRes });
778
901
  const res = fetchHandler(request);
779
902
  return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
780
903
  };
@@ -786,7 +909,7 @@ class NodeServer {
786
909
  const fetchHandler = wrapFetch(this, this.options.fetch);
787
910
  this.fetch = fetchHandler;
788
911
  const handler = (nodeReq, nodeRes) => {
789
- const request = new NodeRequestProxy({ req: nodeReq, res: nodeRes });
912
+ const request = new NodeRequest({ req: nodeReq, res: nodeRes });
790
913
  const res = fetchHandler(request);
791
914
  return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
792
915
  };
@@ -842,4 +965,4 @@ class NodeServer {
842
965
  }
843
966
  }
844
967
 
845
- export { NodeFastResponse as Response, serve, toNodeHandler };
968
+ export { NodeRequest, NodeRequestHeaders, NodeResponse, NodeResponseHeaders, NodeRequest as Request, NodeResponse as Response, serve, toNodeHandler };
package/dist/types.d.mts CHANGED
@@ -161,17 +161,18 @@ interface ServerPluginInstance {
161
161
  */
162
162
  response?: (request: ServerRequest, response: Response) => MaybePromise<void | Response>;
163
163
  }
164
- interface ServerRequest extends Request {
164
+ interface ServerRuntimeContext {
165
+ runtime: "node" | "deno" | "bun" | "cloudflare" | (string & {});
165
166
  /**
166
- * Remote address of the client.
167
+ * IP address of the client.
167
168
  */
168
- remoteAddress?: string | undefined;
169
+ ip?: string | undefined;
169
170
  /**
170
171
  * Underlying Node.js server request info.
171
172
  */
172
173
  node?: {
173
174
  req: NodeHttp.IncomingMessage;
174
- res: NodeHttp.ServerResponse;
175
+ res?: NodeHttp.ServerResponse;
175
176
  };
176
177
  /**
177
178
  * Underlying Deno server request info.
@@ -193,10 +194,16 @@ interface ServerRequest extends Request {
193
194
  context: CF.ExecutionContext;
194
195
  };
195
196
  }
197
+ interface ServerRequest extends Request {
198
+ /**
199
+ * Runtime specific request context.
200
+ */
201
+ x?: ServerRuntimeContext;
202
+ }
196
203
  type FetchHandler = (request: Request) => Response | Promise<Response>;
197
204
  type BunFetchHandler = (request: Request, server?: Bun.Server) => Response | Promise<Response>;
198
205
  type DenoFetchHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.NetAddr>) => Response | Promise<Response>;
199
206
  type NodeHttpHandler = (nodeReq: NodeHttp.IncomingMessage, nodeRes: NodeHttp.ServerResponse) => void | Promise<void>;
200
207
  type CloudflareFetchHandler = CF.ExportedHandlerFetchHandler;
201
208
 
202
- export { type BunFetchHandler, type CloudflareFetchHandler, type DenoFetchHandler, type FetchHandler, type NodeHttpHandler, Response, type Server, type ServerHandler, type ServerOptions, type ServerPlugin, type ServerPluginInstance, type ServerRequest, serve };
209
+ export { type BunFetchHandler, type CloudflareFetchHandler, type DenoFetchHandler, type FetchHandler, type NodeHttpHandler, Response, type Server, type ServerHandler, type ServerOptions, type ServerPlugin, type ServerPluginInstance, type ServerRequest, type ServerRuntimeContext, serve };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "srvx",
3
- "version": "0.2.7",
3
+ "version": "0.3.0",
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",
@@ -13,11 +13,11 @@
13
13
  "./node": "./dist/adapters/node.mjs",
14
14
  "./cloudflare": "./dist/adapters/cloudflare.mjs",
15
15
  ".": {
16
+ "types": "./dist/types.d.mts",
16
17
  "deno": "./dist/adapters/deno.mjs",
17
18
  "bun": "./dist/adapters/bun.mjs",
18
19
  "workerd": "./dist/adapters/cloudflare.mjs",
19
- "node": "./dist/adapters/node.mjs",
20
- "types": "./dist/types.d.mts"
20
+ "node": "./dist/adapters/node.mjs"
21
21
  }
22
22
  },
23
23
  "types": "./dist/types.d.mts",