@orpc/standard-server-node 0.0.0-next.fcb9d5a → 0.0.0-next.fd6982a

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/index.d.mts CHANGED
@@ -1,28 +1,11 @@
1
1
  import { StandardBody, StandardHeaders, StandardLazyRequest, StandardResponse } from '@orpc/standard-server';
2
- import { Readable } from 'node:stream';
2
+ import { ToEventStreamOptions as ToEventStreamOptions$1 } from '@orpc/standard-server-fetch';
3
+ import Stream, { Readable } from 'node:stream';
3
4
  import { IncomingMessage, ServerResponse } from 'node:http';
4
5
  import { Http2ServerRequest, Http2ServerResponse } from 'node:http2';
5
6
 
6
7
  declare function toEventIterator(stream: Readable): AsyncIteratorObject<unknown | void, unknown | void, void> & AsyncGenerator<unknown | void, unknown | void, void>;
7
- interface ToEventStreamOptions {
8
- /**
9
- * If true, a ping comment is sent periodically to keep the connection alive.
10
- *
11
- * @default true
12
- */
13
- eventIteratorKeepAliveEnabled?: boolean;
14
- /**
15
- * Interval (in milliseconds) between ping comments sent after the last event.
16
- *
17
- * @default 5000
18
- */
19
- eventIteratorKeepAliveInterval?: number;
20
- /**
21
- * The content of the ping comment. Must not include newline characters.
22
- *
23
- * @default ''
24
- */
25
- eventIteratorKeepAliveComment?: string;
8
+ interface ToEventStreamOptions extends ToEventStreamOptions$1 {
26
9
  }
27
10
  declare function toEventStream(iterator: AsyncIterator<unknown | void, unknown | void, void>, options?: ToEventStreamOptions): Readable;
28
11
 
@@ -45,13 +28,17 @@ interface ToNodeHttpBodyOptions extends ToEventStreamOptions {
45
28
  */
46
29
  declare function toNodeHttpBody(body: StandardBody, headers: StandardHeaders, options?: ToNodeHttpBodyOptions): Readable | undefined | string;
47
30
 
31
+ declare function toStandardMethod(method: string | undefined): string;
32
+
48
33
  declare function toStandardLazyRequest(req: NodeHttpRequest, res: NodeHttpResponse): StandardLazyRequest;
49
34
 
50
35
  interface SendStandardResponseOptions extends ToNodeHttpBodyOptions {
51
36
  }
52
37
  declare function sendStandardResponse(res: NodeHttpResponse, standardResponse: StandardResponse, options?: SendStandardResponseOptions): Promise<void>;
53
38
 
54
- declare function toAbortSignal(res: NodeHttpResponse): AbortSignal;
39
+ declare function toAbortSignal(stream: Stream.Writable): AbortSignal;
40
+
41
+ declare function toStandardUrl(req: NodeHttpRequest): URL;
55
42
 
56
- export { sendStandardResponse, toAbortSignal, toEventIterator, toEventStream, toNodeHttpBody, toStandardBody, toStandardLazyRequest };
43
+ export { sendStandardResponse, toAbortSignal, toEventIterator, toEventStream, toNodeHttpBody, toStandardBody, toStandardLazyRequest, toStandardMethod, toStandardUrl };
57
44
  export type { NodeHttpRequest, NodeHttpResponse, SendStandardResponseOptions, ToEventStreamOptions, ToNodeHttpBodyOptions };
package/dist/index.d.ts CHANGED
@@ -1,28 +1,11 @@
1
1
  import { StandardBody, StandardHeaders, StandardLazyRequest, StandardResponse } from '@orpc/standard-server';
2
- import { Readable } from 'node:stream';
2
+ import { ToEventStreamOptions as ToEventStreamOptions$1 } from '@orpc/standard-server-fetch';
3
+ import Stream, { Readable } from 'node:stream';
3
4
  import { IncomingMessage, ServerResponse } from 'node:http';
4
5
  import { Http2ServerRequest, Http2ServerResponse } from 'node:http2';
5
6
 
6
7
  declare function toEventIterator(stream: Readable): AsyncIteratorObject<unknown | void, unknown | void, void> & AsyncGenerator<unknown | void, unknown | void, void>;
7
- interface ToEventStreamOptions {
8
- /**
9
- * If true, a ping comment is sent periodically to keep the connection alive.
10
- *
11
- * @default true
12
- */
13
- eventIteratorKeepAliveEnabled?: boolean;
14
- /**
15
- * Interval (in milliseconds) between ping comments sent after the last event.
16
- *
17
- * @default 5000
18
- */
19
- eventIteratorKeepAliveInterval?: number;
20
- /**
21
- * The content of the ping comment. Must not include newline characters.
22
- *
23
- * @default ''
24
- */
25
- eventIteratorKeepAliveComment?: string;
8
+ interface ToEventStreamOptions extends ToEventStreamOptions$1 {
26
9
  }
27
10
  declare function toEventStream(iterator: AsyncIterator<unknown | void, unknown | void, void>, options?: ToEventStreamOptions): Readable;
28
11
 
@@ -45,13 +28,17 @@ interface ToNodeHttpBodyOptions extends ToEventStreamOptions {
45
28
  */
46
29
  declare function toNodeHttpBody(body: StandardBody, headers: StandardHeaders, options?: ToNodeHttpBodyOptions): Readable | undefined | string;
47
30
 
31
+ declare function toStandardMethod(method: string | undefined): string;
32
+
48
33
  declare function toStandardLazyRequest(req: NodeHttpRequest, res: NodeHttpResponse): StandardLazyRequest;
49
34
 
50
35
  interface SendStandardResponseOptions extends ToNodeHttpBodyOptions {
51
36
  }
52
37
  declare function sendStandardResponse(res: NodeHttpResponse, standardResponse: StandardResponse, options?: SendStandardResponseOptions): Promise<void>;
53
38
 
54
- declare function toAbortSignal(res: NodeHttpResponse): AbortSignal;
39
+ declare function toAbortSignal(stream: Stream.Writable): AbortSignal;
40
+
41
+ declare function toStandardUrl(req: NodeHttpRequest): URL;
55
42
 
56
- export { sendStandardResponse, toAbortSignal, toEventIterator, toEventStream, toNodeHttpBody, toStandardBody, toStandardLazyRequest };
43
+ export { sendStandardResponse, toAbortSignal, toEventIterator, toEventStream, toNodeHttpBody, toStandardBody, toStandardLazyRequest, toStandardMethod, toStandardUrl };
57
44
  export type { NodeHttpRequest, NodeHttpResponse, SendStandardResponseOptions, ToEventStreamOptions, ToNodeHttpBodyOptions };
package/dist/index.mjs CHANGED
@@ -1,103 +1,16 @@
1
1
  import { Readable } from 'node:stream';
2
- import { createAsyncIteratorObject, parseEmptyableJSON, isTypescriptObject, stringifyJSON, isAsyncIteratorObject, once } from '@orpc/shared';
3
- import { EventDecoderStream, withEventMeta, ErrorEvent, encodeEventMessage, getEventMeta, getFilenameFromContentDisposition, flattenHeader, generateContentDisposition } from '@orpc/standard-server';
2
+ import { parseEmptyableJSON, isAsyncIteratorObject, stringifyJSON, once } from '@orpc/shared';
3
+ import { getFilenameFromContentDisposition, flattenHeader, generateContentDisposition } from '@orpc/standard-server';
4
+ import { toEventIterator as toEventIterator$1, toEventStream as toEventStream$1 } from '@orpc/standard-server-fetch';
4
5
 
5
6
  function toEventIterator(stream) {
6
- const eventStream = Readable.toWeb(stream).pipeThrough(new TextDecoderStream()).pipeThrough(new EventDecoderStream());
7
- const reader = eventStream.getReader();
8
- return createAsyncIteratorObject(async () => {
9
- while (true) {
10
- const { done, value } = await reader.read();
11
- if (done) {
12
- return { done: true, value: void 0 };
13
- }
14
- switch (value.event) {
15
- case "message": {
16
- let message = parseEmptyableJSON(value.data);
17
- if (isTypescriptObject(message)) {
18
- message = withEventMeta(message, value);
19
- }
20
- return { done: false, value: message };
21
- }
22
- case "error": {
23
- let error = new ErrorEvent({
24
- data: parseEmptyableJSON(value.data)
25
- });
26
- error = withEventMeta(error, value);
27
- throw error;
28
- }
29
- case "done": {
30
- let done2 = parseEmptyableJSON(value.data);
31
- if (isTypescriptObject(done2)) {
32
- done2 = withEventMeta(done2, value);
33
- }
34
- return { done: true, value: done2 };
35
- }
36
- }
37
- }
38
- }, async () => {
39
- await reader.cancel();
40
- });
7
+ return toEventIterator$1(Readable.toWeb(stream));
41
8
  }
42
9
  function toEventStream(iterator, options = {}) {
43
- const keepAliveEnabled = options.eventIteratorKeepAliveEnabled ?? true;
44
- const keepAliveInterval = options.eventIteratorKeepAliveInterval ?? 5e3;
45
- const keepAliveComment = options.eventIteratorKeepAliveComment ?? "";
46
- let cancelled = false;
47
- let timeout;
48
- const stream = new ReadableStream({
49
- async pull(controller) {
50
- try {
51
- if (keepAliveEnabled) {
52
- timeout = setInterval(() => {
53
- controller.enqueue(encodeEventMessage({
54
- comments: [keepAliveComment]
55
- }));
56
- }, keepAliveInterval);
57
- }
58
- const value = await iterator.next();
59
- clearInterval(timeout);
60
- if (cancelled) {
61
- return;
62
- }
63
- const meta = getEventMeta(value.value);
64
- if (!value.done || value.value !== void 0 || meta !== void 0) {
65
- controller.enqueue(encodeEventMessage({
66
- ...meta,
67
- event: value.done ? "done" : "message",
68
- data: stringifyJSON(value.value)
69
- }));
70
- }
71
- if (value.done) {
72
- controller.close();
73
- }
74
- } catch (err) {
75
- clearInterval(timeout);
76
- if (cancelled) {
77
- return;
78
- }
79
- controller.enqueue(encodeEventMessage({
80
- ...getEventMeta(err),
81
- event: "error",
82
- data: err instanceof ErrorEvent ? stringifyJSON(err.data) : void 0
83
- }));
84
- controller.close();
85
- }
86
- },
87
- async cancel() {
88
- cancelled = true;
89
- clearInterval(timeout);
90
- await iterator.return?.();
91
- }
92
- });
93
- return Readable.fromWeb(stream);
10
+ return Readable.fromWeb(toEventStream$1(iterator, options));
94
11
  }
95
12
 
96
13
  async function toStandardBody(req) {
97
- const method = req.method ?? "GET";
98
- if (method === "GET" || method === "HEAD") {
99
- return void 0;
100
- }
101
14
  const contentDisposition = req.headers["content-disposition"];
102
15
  const contentType = req.headers["content-type"];
103
16
  if (typeof contentDisposition === "string") {
@@ -177,28 +90,32 @@ async function _streamToFile(stream, fileName, contentType) {
177
90
  return new File(chunks, fileName, { type: contentType });
178
91
  }
179
92
 
180
- function toAbortSignal(res) {
93
+ function toStandardMethod(method) {
94
+ return method ?? "GET";
95
+ }
96
+
97
+ function toAbortSignal(stream) {
181
98
  const controller = new AbortController();
182
- res.on("close", () => {
183
- if (res.errored) {
184
- controller.abort(res.errored.toString());
185
- } else if (!res.writableFinished) {
186
- controller.abort("Client connection prematurely closed.");
187
- } else {
188
- controller.abort("Server closed the connection.");
99
+ stream.once("error", (error) => controller.abort(error));
100
+ stream.once("close", () => {
101
+ if (!stream.writableFinished) {
102
+ controller.abort(new Error("Writable stream closed before it finished writing"));
189
103
  }
190
104
  });
191
105
  return controller.signal;
192
106
  }
193
107
 
194
- function toStandardLazyRequest(req, res) {
195
- const method = req.method ?? "GET";
108
+ function toStandardUrl(req) {
196
109
  const protocol = "encrypted" in req.socket && req.socket.encrypted ? "https:" : "http:";
197
110
  const host = req.headers.host ?? "localhost";
198
111
  const url = new URL(req.originalUrl ?? req.url ?? "/", `${protocol}//${host}`);
112
+ return url;
113
+ }
114
+
115
+ function toStandardLazyRequest(req, res) {
199
116
  return {
200
- method,
201
- url,
117
+ method: toStandardMethod(req.method),
118
+ url: toStandardUrl(req),
202
119
  headers: req.headers,
203
120
  body: once(() => toStandardBody(req)),
204
121
  signal: toAbortSignal(res)
@@ -207,24 +124,25 @@ function toStandardLazyRequest(req, res) {
207
124
 
208
125
  function sendStandardResponse(res, standardResponse, options = {}) {
209
126
  return new Promise((resolve, reject) => {
210
- res.on("error", reject);
211
- res.on("finish", resolve);
127
+ res.once("error", reject);
128
+ res.once("close", resolve);
212
129
  const resHeaders = { ...standardResponse.headers };
213
130
  const resBody = toNodeHttpBody(standardResponse.body, resHeaders, options);
214
131
  res.writeHead(standardResponse.status, resHeaders);
215
132
  if (resBody === void 0) {
216
- res.end(resBody);
133
+ res.end();
217
134
  } else if (typeof resBody === "string") {
218
135
  res.end(resBody);
219
136
  } else {
220
- res.on("close", () => {
137
+ res.once("close", () => {
221
138
  if (!resBody.closed) {
222
139
  resBody.destroy(res.errored ?? void 0);
223
140
  }
224
141
  });
142
+ resBody.once("error", (error) => res.destroy(error));
225
143
  resBody.pipe(res);
226
144
  }
227
145
  });
228
146
  }
229
147
 
230
- export { sendStandardResponse, toAbortSignal, toEventIterator, toEventStream, toNodeHttpBody, toStandardBody, toStandardLazyRequest };
148
+ export { sendStandardResponse, toAbortSignal, toEventIterator, toEventStream, toNodeHttpBody, toStandardBody, toStandardLazyRequest, toStandardMethod, toStandardUrl };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/standard-server-node",
3
3
  "type": "module",
4
- "version": "0.0.0-next.fcb9d5a",
4
+ "version": "0.0.0-next.fd6982a",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -23,11 +23,12 @@
23
23
  "dist"
24
24
  ],
25
25
  "dependencies": {
26
- "@orpc/shared": "0.0.0-next.fcb9d5a",
27
- "@orpc/standard-server": "0.0.0-next.fcb9d5a"
26
+ "@orpc/standard-server": "0.0.0-next.fd6982a",
27
+ "@orpc/standard-server-fetch": "0.0.0-next.fd6982a",
28
+ "@orpc/shared": "0.0.0-next.fd6982a"
28
29
  },
29
30
  "devDependencies": {
30
- "@types/node": "^22.14.1",
31
+ "@types/node": "^22.15.17",
31
32
  "@types/supertest": "^6.0.3",
32
33
  "supertest": "^7.1.0"
33
34
  },