@trpc/server 11.0.0-rc.359 → 11.0.0-rc.362

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.
Files changed (168) hide show
  1. package/dist/@trpc/server/http.d.ts +7 -6
  2. package/dist/@trpc/server/http.d.ts.map +1 -1
  3. package/dist/@trpc/server/index.d.ts +1 -1
  4. package/dist/@trpc/server/index.d.ts.map +1 -1
  5. package/dist/adapters/aws-lambda/getPlanner.d.ts +13 -0
  6. package/dist/adapters/aws-lambda/getPlanner.d.ts.map +1 -0
  7. package/dist/adapters/aws-lambda/getPlanner.js +143 -0
  8. package/dist/adapters/aws-lambda/getPlanner.mjs +141 -0
  9. package/dist/adapters/aws-lambda/index.d.ts +12 -9
  10. package/dist/adapters/aws-lambda/index.d.ts.map +1 -1
  11. package/dist/adapters/aws-lambda/index.js +6 -65
  12. package/dist/adapters/aws-lambda/index.mjs +8 -61
  13. package/dist/adapters/express.d.ts.map +1 -1
  14. package/dist/adapters/express.js +1 -1
  15. package/dist/adapters/express.mjs +1 -1
  16. package/dist/adapters/fastify/fastifyRequestHandler.d.ts +10 -1
  17. package/dist/adapters/fastify/fastifyRequestHandler.d.ts.map +1 -1
  18. package/dist/adapters/fastify/fastifyRequestHandler.js +12 -55
  19. package/dist/adapters/fastify/fastifyRequestHandler.mjs +13 -56
  20. package/dist/adapters/fastify/fastifyTRPCPlugin.d.ts +1 -1
  21. package/dist/adapters/fastify/fastifyTRPCPlugin.d.ts.map +1 -1
  22. package/dist/adapters/fetch/fetchRequestHandler.d.ts +1 -5
  23. package/dist/adapters/fetch/fetchRequestHandler.d.ts.map +1 -1
  24. package/dist/adapters/fetch/fetchRequestHandler.js +28 -71
  25. package/dist/adapters/fetch/fetchRequestHandler.mjs +29 -72
  26. package/dist/adapters/fetch/types.d.ts +9 -12
  27. package/dist/adapters/fetch/types.d.ts.map +1 -1
  28. package/dist/adapters/next-app-dir/nextAppDirCaller.d.ts +2 -7
  29. package/dist/adapters/next-app-dir/nextAppDirCaller.d.ts.map +1 -1
  30. package/dist/adapters/next.d.ts.map +1 -1
  31. package/dist/adapters/next.js +1 -2
  32. package/dist/adapters/next.mjs +1 -2
  33. package/dist/adapters/node-http/incomingMessageToRequest.d.ts +18 -0
  34. package/dist/adapters/node-http/incomingMessageToRequest.d.ts.map +1 -0
  35. package/dist/adapters/node-http/incomingMessageToRequest.js +71 -0
  36. package/dist/adapters/node-http/incomingMessageToRequest.mjs +69 -0
  37. package/dist/adapters/node-http/index.d.ts +1 -0
  38. package/dist/adapters/node-http/index.d.ts.map +1 -1
  39. package/dist/adapters/node-http/index.js +2 -0
  40. package/dist/adapters/node-http/index.mjs +1 -0
  41. package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts +1 -1
  42. package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts.map +1 -1
  43. package/dist/adapters/node-http/nodeHTTPRequestHandler.js +27 -72
  44. package/dist/adapters/node-http/nodeHTTPRequestHandler.mjs +28 -73
  45. package/dist/adapters/node-http/types.d.ts +2 -14
  46. package/dist/adapters/node-http/types.d.ts.map +1 -1
  47. package/dist/adapters/standalone.d.ts.map +1 -1
  48. package/dist/adapters/standalone.js +0 -1
  49. package/dist/adapters/standalone.mjs +0 -1
  50. package/dist/adapters/ws.d.ts +2 -12
  51. package/dist/adapters/ws.d.ts.map +1 -1
  52. package/dist/adapters/ws.js +1 -1
  53. package/dist/adapters/ws.mjs +1 -1
  54. package/dist/bundle-analysis.json +173 -259
  55. package/dist/http.js +4 -4
  56. package/dist/http.mjs +2 -2
  57. package/dist/index.js +2 -2
  58. package/dist/index.mjs +1 -1
  59. package/dist/unstable-core-do-not-import/http/contentType.d.ts +8 -28
  60. package/dist/unstable-core-do-not-import/http/contentType.d.ts.map +1 -1
  61. package/dist/unstable-core-do-not-import/http/contentType.js +164 -38
  62. package/dist/unstable-core-do-not-import/http/contentType.mjs +164 -38
  63. package/dist/unstable-core-do-not-import/http/contentTypeParsers.d.ts +14 -0
  64. package/dist/unstable-core-do-not-import/http/contentTypeParsers.d.ts.map +1 -0
  65. package/dist/unstable-core-do-not-import/http/contentTypeParsers.js +14 -0
  66. package/dist/unstable-core-do-not-import/http/contentTypeParsers.mjs +12 -0
  67. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.d.ts +1 -1
  68. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.d.ts.map +1 -1
  69. package/dist/unstable-core-do-not-import/http/resolveHTTPResponse.d.ts +7 -43
  70. package/dist/unstable-core-do-not-import/http/resolveHTTPResponse.d.ts.map +1 -1
  71. package/dist/unstable-core-do-not-import/http/resolveHTTPResponse.js +115 -124
  72. package/dist/unstable-core-do-not-import/http/resolveHTTPResponse.mjs +116 -125
  73. package/dist/unstable-core-do-not-import/http/types.d.ts +25 -29
  74. package/dist/unstable-core-do-not-import/http/types.d.ts.map +1 -1
  75. package/dist/unstable-core-do-not-import/initTRPC.d.ts +1 -1
  76. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +1 -3
  77. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
  78. package/dist/unstable-core-do-not-import/procedureBuilder.js +0 -2
  79. package/dist/unstable-core-do-not-import/procedureBuilder.mjs +1 -2
  80. package/dist/unstable-core-do-not-import/rootConfig.d.ts +12 -0
  81. package/dist/unstable-core-do-not-import/rootConfig.d.ts.map +1 -1
  82. package/dist/unstable-core-do-not-import/utils.d.ts +3 -0
  83. package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
  84. package/dist/unstable-core-do-not-import/utils.js +2 -0
  85. package/dist/unstable-core-do-not-import/utils.mjs +2 -1
  86. package/dist/unstable-core-do-not-import.d.ts +9 -3
  87. package/dist/unstable-core-do-not-import.d.ts.map +1 -1
  88. package/dist/unstable-core-do-not-import.js +11 -9
  89. package/dist/unstable-core-do-not-import.mjs +7 -6
  90. package/package.json +3 -14
  91. package/src/@trpc/server/http.ts +7 -13
  92. package/src/@trpc/server/index.ts +1 -0
  93. package/src/adapters/aws-lambda/getPlanner.ts +191 -0
  94. package/src/adapters/aws-lambda/index.ts +43 -92
  95. package/src/adapters/express.ts +1 -6
  96. package/src/adapters/fastify/fastifyRequestHandler.ts +22 -77
  97. package/src/adapters/fastify/fastifyTRPCPlugin.ts +1 -1
  98. package/src/adapters/fetch/fetchRequestHandler.ts +34 -98
  99. package/src/adapters/fetch/types.ts +24 -15
  100. package/src/adapters/next-app-dir/nextAppDirCaller.ts +2 -9
  101. package/src/adapters/next.ts +1 -6
  102. package/src/adapters/node-http/incomingMessageToRequest.ts +94 -0
  103. package/src/adapters/node-http/index.ts +1 -0
  104. package/src/adapters/node-http/nodeHTTPRequestHandler.ts +31 -110
  105. package/src/adapters/node-http/types.ts +9 -19
  106. package/src/adapters/standalone.ts +1 -2
  107. package/src/adapters/ws.ts +9 -14
  108. package/src/unstable-core-do-not-import/http/contentType.ts +199 -82
  109. package/src/unstable-core-do-not-import/http/contentTypeParsers.ts +29 -0
  110. package/src/unstable-core-do-not-import/http/getHTTPStatusCode.ts +2 -2
  111. package/src/unstable-core-do-not-import/http/resolveHTTPResponse.ts +133 -205
  112. package/src/unstable-core-do-not-import/http/types.ts +25 -32
  113. package/src/unstable-core-do-not-import/procedureBuilder.ts +2 -4
  114. package/src/unstable-core-do-not-import/rootConfig.ts +21 -0
  115. package/src/unstable-core-do-not-import/utils.ts +4 -0
  116. package/src/unstable-core-do-not-import.ts +9 -3
  117. package/adapters/node-http/content-type/form-data/index.d.ts +0 -1
  118. package/adapters/node-http/content-type/form-data/index.js +0 -1
  119. package/adapters/node-http/content-type/json/index.d.ts +0 -1
  120. package/adapters/node-http/content-type/json/index.js +0 -1
  121. package/dist/adapters/aws-lambda/utils.d.ts +0 -40
  122. package/dist/adapters/aws-lambda/utils.d.ts.map +0 -1
  123. package/dist/adapters/aws-lambda/utils.js +0 -100
  124. package/dist/adapters/aws-lambda/utils.mjs +0 -93
  125. package/dist/adapters/node-http/content-type/form-data/fileUploadHandler.d.ts +0 -73
  126. package/dist/adapters/node-http/content-type/form-data/fileUploadHandler.d.ts.map +0 -1
  127. package/dist/adapters/node-http/content-type/form-data/fileUploadHandler.js +0 -161
  128. package/dist/adapters/node-http/content-type/form-data/fileUploadHandler.mjs +0 -157
  129. package/dist/adapters/node-http/content-type/form-data/index.d.ts +0 -26
  130. package/dist/adapters/node-http/content-type/form-data/index.d.ts.map +0 -1
  131. package/dist/adapters/node-http/content-type/form-data/index.js +0 -135
  132. package/dist/adapters/node-http/content-type/form-data/index.mjs +0 -108
  133. package/dist/adapters/node-http/content-type/form-data/memoryUploadHandler.d.ts +0 -31
  134. package/dist/adapters/node-http/content-type/form-data/memoryUploadHandler.d.ts.map +0 -1
  135. package/dist/adapters/node-http/content-type/form-data/memoryUploadHandler.js +0 -29
  136. package/dist/adapters/node-http/content-type/form-data/memoryUploadHandler.mjs +0 -27
  137. package/dist/adapters/node-http/content-type/form-data/streamSlice.d.ts +0 -16
  138. package/dist/adapters/node-http/content-type/form-data/streamSlice.d.ts.map +0 -1
  139. package/dist/adapters/node-http/content-type/form-data/streamSlice.js +0 -46
  140. package/dist/adapters/node-http/content-type/form-data/streamSlice.mjs +0 -44
  141. package/dist/adapters/node-http/content-type/form-data/uploadHandler.d.ts +0 -45
  142. package/dist/adapters/node-http/content-type/form-data/uploadHandler.d.ts.map +0 -1
  143. package/dist/adapters/node-http/content-type/form-data/uploadHandler.js +0 -30
  144. package/dist/adapters/node-http/content-type/form-data/uploadHandler.mjs +0 -26
  145. package/dist/adapters/node-http/content-type/json/getPostBody.d.ts +0 -7
  146. package/dist/adapters/node-http/content-type/json/getPostBody.d.ts.map +0 -1
  147. package/dist/adapters/node-http/content-type/json/getPostBody.js +0 -53
  148. package/dist/adapters/node-http/content-type/json/getPostBody.mjs +0 -51
  149. package/dist/adapters/node-http/content-type/json/index.d.ts +0 -2
  150. package/dist/adapters/node-http/content-type/json/index.d.ts.map +0 -1
  151. package/dist/adapters/node-http/content-type/json/index.js +0 -16
  152. package/dist/adapters/node-http/content-type/json/index.mjs +0 -14
  153. package/dist/adapters/node-http/internals/contentType.d.ts +0 -9
  154. package/dist/adapters/node-http/internals/contentType.d.ts.map +0 -1
  155. package/dist/adapters/node-http/internals/contentType.js +0 -8
  156. package/dist/adapters/node-http/internals/contentType.mjs +0 -6
  157. package/dist/unstable-core-do-not-import/http/index.d.ts +0 -12
  158. package/dist/unstable-core-do-not-import/http/index.d.ts.map +0 -1
  159. package/src/adapters/aws-lambda/utils.ts +0 -164
  160. package/src/adapters/node-http/content-type/form-data/fileUploadHandler.ts +0 -277
  161. package/src/adapters/node-http/content-type/form-data/index.ts +0 -163
  162. package/src/adapters/node-http/content-type/form-data/memoryUploadHandler.ts +0 -56
  163. package/src/adapters/node-http/content-type/form-data/streamSlice.ts +0 -56
  164. package/src/adapters/node-http/content-type/form-data/uploadHandler.ts +0 -89
  165. package/src/adapters/node-http/content-type/json/getPostBody.ts +0 -58
  166. package/src/adapters/node-http/content-type/json/index.ts +0 -11
  167. package/src/adapters/node-http/internals/contentType.ts +0 -31
  168. package/src/unstable-core-do-not-import/http/index.ts +0 -29
@@ -9,12 +9,12 @@
9
9
  */
10
10
  /// <reference types="@fastify/websocket" />
11
11
  import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
12
- import type { FastifyHandlerOptions } from '.';
13
12
  // @trpc/server
14
13
  import type { AnyRouter } from '../../@trpc/server';
15
14
  import type { NodeHTTPCreateContextFnOptions } from '../node-http';
16
15
  import type { WSSHandlerOptions } from '../ws';
17
16
  import { getWSConnectionHandler } from '../ws';
17
+ import type { FastifyHandlerOptions } from './fastifyRequestHandler';
18
18
  import { fastifyRequestHandler } from './fastifyRequestHandler';
19
19
 
20
20
  export interface FastifyTRPCPluginOptions<TRouter extends AnyRouter> {
@@ -10,24 +10,9 @@
10
10
  // @trpc/server
11
11
 
12
12
  import type { AnyRouter } from '../../@trpc/server';
13
- import type {
14
- HTTPRequest,
15
- HTTPResponse,
16
- ResolveHTTPRequestOptionsContextFn,
17
- ResponseChunk,
18
- } from '../../@trpc/server/http';
19
- import {
20
- getBatchStreamFormatter,
21
- resolveHTTPResponse,
22
- toURL,
23
- } from '../../@trpc/server/http';
24
- import type { FetchHandlerOptions } from './types';
25
-
26
- export type FetchHandlerRequestOptions<TRouter extends AnyRouter> =
27
- FetchHandlerOptions<TRouter> & {
28
- req: Request;
29
- endpoint: string;
30
- };
13
+ import type { ResolveHTTPRequestOptionsContextFn } from '../../@trpc/server/http';
14
+ import { resolveResponse, toURL } from '../../@trpc/server/http';
15
+ import type { FetchHandlerRequestOptions } from './types';
31
16
 
32
17
  const trimSlashes = (path: string): string => {
33
18
  path = path.startsWith('/') ? path.slice(1) : path;
@@ -53,92 +38,43 @@ export async function fetchRequestHandler<TRouter extends AnyRouter>(
53
38
  const endpoint = trimSlashes(opts.endpoint);
54
39
  const path = trimSlashes(pathname.slice(endpoint.length));
55
40
 
56
- const req: HTTPRequest = {
57
- query: url.searchParams,
58
- method: opts.req.method,
59
- headers: Object.fromEntries(opts.req.headers),
60
- body: opts.req.headers.get('content-type')?.startsWith('application/json')
61
- ? await opts.req.text()
62
- : '',
63
- };
64
-
65
- let resolve: (value: Response) => void;
66
- const promise = new Promise<Response>((r) => (resolve = r));
67
- let status = 200;
68
-
69
- let isStream = false;
70
- let controller: ReadableStreamController<any>;
71
- let encoder: TextEncoder;
72
- let formatter: ReturnType<typeof getBatchStreamFormatter>;
73
- const unstable_onHead = (head: HTTPResponse, isStreaming: boolean) => {
74
- for (const [key, value] of Object.entries(head.headers ?? {})) {
75
- /* istanbul ignore if -- @preserve */
76
- if (typeof value === 'undefined') {
77
- continue;
78
- }
79
- if (typeof value === 'string') {
80
- resHeaders.set(key, value);
81
- continue;
82
- }
83
- for (const v of value) {
84
- resHeaders.append(key, v);
85
- }
86
- }
87
- status = head.status;
88
- if (isStreaming) {
89
- resHeaders.set('Transfer-Encoding', 'chunked');
90
- resHeaders.append('Vary', 'trpc-batch-mode');
91
- const stream = new ReadableStream({
92
- start(c) {
93
- controller = c;
94
- },
95
- });
96
- const response = new Response(stream, {
97
- status,
98
- headers: resHeaders,
99
- });
100
- resolve(response);
101
- encoder = new TextEncoder();
102
- formatter = getBatchStreamFormatter();
103
- isStream = true;
104
- }
105
- };
106
-
107
- const unstable_onChunk = ([index, string]: ResponseChunk) => {
108
- if (index === -1) {
109
- // full response, no streaming
110
- const response = new Response(string || null, {
111
- status,
112
- headers: resHeaders,
113
- });
114
- resolve(response);
115
- } else {
116
- controller.enqueue(encoder.encode(formatter(index, string)));
117
- }
118
- };
119
-
120
- resolveHTTPResponse({
41
+ return await resolveResponse({
121
42
  ...opts,
122
- req,
43
+ req: opts.req,
123
44
  createContext,
124
45
  path,
46
+ error: null,
125
47
  onError(o) {
126
48
  opts?.onError?.({ ...o, req: opts.req });
127
49
  },
128
- unstable_onHead,
129
- unstable_onChunk,
130
- })
131
- .then(() => {
132
- if (isStream) {
133
- controller.enqueue(encoder.encode(formatter.end()));
134
- controller.close();
135
- }
136
- })
137
- .catch(() => {
138
- if (isStream) {
139
- controller.close();
50
+ responseMeta(data) {
51
+ const meta = opts.responseMeta?.(data);
52
+
53
+ if (meta?.headers) {
54
+ if (meta.headers instanceof Headers) {
55
+ for (const [key, value] of meta.headers.entries()) {
56
+ resHeaders.append(key, value);
57
+ }
58
+ } else {
59
+ /**
60
+ * @deprecated, delete in v12
61
+ */
62
+ for (const [key, value] of Object.entries(meta.headers)) {
63
+ if (Array.isArray(value)) {
64
+ for (const v of value) {
65
+ resHeaders.append(key, v);
66
+ }
67
+ } else if (typeof value === 'string') {
68
+ resHeaders.set(key, value);
69
+ }
70
+ }
71
+ }
140
72
  }
141
- });
142
73
 
143
- return promise;
74
+ return {
75
+ headers: resHeaders,
76
+ status: meta?.status,
77
+ };
78
+ },
79
+ });
144
80
  }
@@ -8,7 +8,11 @@
8
8
  * ```
9
9
  */
10
10
  // @trpc/server
11
- import type { AnyRouter, inferRouterContext } from '../../@trpc/server';
11
+ import type {
12
+ AnyRouter,
13
+ CreateContextCallback,
14
+ inferRouterContext,
15
+ } from '../../@trpc/server';
12
16
  // @trpc/server/http
13
17
  import type {
14
18
  HTTPBaseHandlerOptions,
@@ -26,19 +30,24 @@ export type FetchCreateContextFn<TRouter extends AnyRouter> = (
26
30
  ) => inferRouterContext<TRouter> | Promise<inferRouterContext<TRouter>>;
27
31
 
28
32
  export type FetchCreateContextOption<TRouter extends AnyRouter> =
29
- unknown extends inferRouterContext<TRouter>
30
- ? {
31
- /**
32
- * @link https://trpc.io/docs/v11/context
33
- **/
34
- createContext?: FetchCreateContextFn<TRouter>;
35
- }
36
- : {
37
- /**
38
- * @link https://trpc.io/docs/v11/context
39
- **/
40
- createContext: FetchCreateContextFn<TRouter>;
41
- };
33
+ CreateContextCallback<
34
+ inferRouterContext<TRouter>,
35
+ FetchCreateContextFn<TRouter>
36
+ >;
42
37
 
43
38
  export type FetchHandlerOptions<TRouter extends AnyRouter> =
44
- FetchCreateContextOption<TRouter> & HTTPBaseHandlerOptions<TRouter, Request>;
39
+ FetchCreateContextOption<TRouter> &
40
+ HTTPBaseHandlerOptions<TRouter, Request> & {
41
+ req: Request;
42
+ endpoint: string;
43
+ };
44
+
45
+ export type FetchHandlerRequestOptions<TRouter extends AnyRouter> =
46
+ HTTPBaseHandlerOptions<TRouter, Request> &
47
+ CreateContextCallback<
48
+ inferRouterContext<TRouter>,
49
+ FetchCreateContextFn<TRouter>
50
+ > & {
51
+ req: Request;
52
+ endpoint: string;
53
+ };
@@ -1,3 +1,4 @@
1
+ import type { CreateContextCallback } from '../../@trpc/server';
1
2
  import { getTRPCErrorFromUnknown, TRPCError } from '../../@trpc/server';
2
3
  // FIXME: fix lint rule, this is ok
3
4
  // eslint-disable-next-line no-restricted-imports
@@ -15,14 +16,6 @@ import { formDataToObject } from './formDataToObject';
15
16
  import { TRPCRedirectError } from './redirect';
16
17
  import { rethrowNextErrors } from './rethrowNextErrors';
17
18
 
18
- type ContextCallback<TContext> = object extends TContext
19
- ? {
20
- createContext?: () => MaybePromise<TContext>;
21
- }
22
- : {
23
- createContext: () => MaybePromise<TContext>;
24
- };
25
-
26
19
  /**
27
20
  * Create a caller that works with Next.js React Server Components & Server Actions
28
21
  */
@@ -38,7 +31,7 @@ export function nextAppDirCaller<TContext>(
38
31
  * Called when an error occurs in the handler
39
32
  */
40
33
  onError?: (opts: ErrorHandlerOptions<TContext>) => void;
41
- } & ContextCallback<TContext>
34
+ } & CreateContextCallback<TContext, () => MaybePromise<TContext>>
42
35
  >,
43
36
  ): CallerOverride<TContext> {
44
37
  const {
@@ -65,12 +65,7 @@ export function createNextApiHandler<TRouter extends AnyRouter>(
65
65
  }
66
66
 
67
67
  await nodeHTTPRequestHandler({
68
- // FIXME: no typecasting should be needed here
69
- ...(opts as NodeHTTPHandlerOptions<
70
- AnyRouter,
71
- NextApiRequest,
72
- NextApiResponse
73
- >),
68
+ ...(opts as any),
74
69
  req,
75
70
  res,
76
71
  path,
@@ -0,0 +1,94 @@
1
+ import type * as http from 'http';
2
+ import { TRPCError } from '../../@trpc/server';
3
+
4
+ export interface IncomingMessageWithBody extends http.IncomingMessage {
5
+ /**
6
+ * Many adapters will add a `body` property to the incoming message and pre-parse the body
7
+ */
8
+ body?: unknown;
9
+ }
10
+ /**
11
+ * Convert an incoming message to a body stream with a max size
12
+ */
13
+ function incomingMessageToBodyStream(
14
+ req: IncomingMessageWithBody,
15
+ opts: { maxBodySize: number | null },
16
+ ) {
17
+ type Value = Buffer | Uint8Array | string | null;
18
+ let size = 0;
19
+ const maxBodySize = opts.maxBodySize;
20
+
21
+ let controller: ReadableStreamDefaultController<Value> =
22
+ null as unknown as ReadableStreamDefaultController<Value>;
23
+ const stream = new ReadableStream<Value>({
24
+ start(c) {
25
+ controller = c;
26
+ },
27
+ async pull(c) {
28
+ const chunk: Value = req.read();
29
+
30
+ if (chunk) {
31
+ size += chunk.length;
32
+ }
33
+ if (maxBodySize !== null && size > maxBodySize) {
34
+ controller.error(
35
+ new TRPCError({
36
+ code: 'PAYLOAD_TOO_LARGE',
37
+ }),
38
+ );
39
+ return;
40
+ }
41
+ if (chunk === null) {
42
+ c.close();
43
+ return;
44
+ }
45
+ controller.enqueue(chunk);
46
+ },
47
+ cancel() {
48
+ req.destroy();
49
+ },
50
+ });
51
+
52
+ return stream;
53
+ }
54
+
55
+ const bodyMethods = ['POST', 'PUT', 'PATCH'];
56
+ /**
57
+ * Convert an [`IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage) to a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
58
+ */
59
+ export function incomingMessageToRequest(
60
+ req: http.IncomingMessage,
61
+ opts: {
62
+ /**
63
+ * Max body size in bytes. If the body is larger than this, the request will be aborted
64
+ */
65
+ maxBodySize: number | null;
66
+ },
67
+ ): Request {
68
+ const ac = new AbortController();
69
+ const headers = new Headers(req.headers as any);
70
+ const url = `http://${headers.get('host')}${req.url}`;
71
+
72
+ req.once('aborted', () => ac.abort());
73
+
74
+ const init: RequestInit = {
75
+ headers,
76
+ method: req.method,
77
+ signal: ac.signal,
78
+ // @ts-expect-error this is fine
79
+ duplex: 'half',
80
+ };
81
+
82
+ if (req.method && bodyMethods.includes(req.method)) {
83
+ if (!('body' in req)) {
84
+ init.body = incomingMessageToBodyStream(req, opts);
85
+ } else if (typeof req.body === 'string') {
86
+ init.body = req.body;
87
+ } else if (req.body !== undefined) {
88
+ init.body = JSON.stringify(req.body);
89
+ }
90
+ }
91
+ const request = new Request(url, init);
92
+
93
+ return request;
94
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './nodeHTTPRequestHandler';
2
2
  export * from './types';
3
+ export * from './incomingMessageToRequest';
@@ -7,28 +7,26 @@
7
7
  * import type { HTTPBaseHandlerOptions } from '@trpc/server/http'
8
8
  * ```
9
9
  */
10
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
10
+
11
11
  // @trpc/server
12
- import type { AnyRouter } from '../../@trpc/server';
13
- import type {
14
- HTTPRequest,
15
- HTTPResponse,
16
- ResolveHTTPRequestOptionsContextFn,
17
- ResponseChunk,
18
- } from '../../@trpc/server/http';
19
- import {
20
- getBatchStreamFormatter,
21
- resolveHTTPResponse,
22
- } from '../../@trpc/server/http';
23
- import { nodeHTTPJSONContentTypeHandler } from './content-type/json';
24
- import type { NodeHTTPContentTypeHandler } from './internals/contentType';
12
+
13
+ import { getTRPCErrorFromUnknown, type AnyRouter } from '../../@trpc/server';
14
+ import type { ResolveHTTPRequestOptionsContextFn } from '../../@trpc/server/http';
15
+ import { resolveResponse } from '../../@trpc/server/http';
16
+ import { incomingMessageToRequest } from './incomingMessageToRequest';
25
17
  import type {
26
18
  NodeHTTPRequest,
27
19
  NodeHTTPRequestHandlerOptions,
28
20
  NodeHTTPResponse,
29
21
  } from './types';
30
22
 
31
- const defaultJSONContentTypeHandler = nodeHTTPJSONContentTypeHandler();
23
+ function assertAsyncIterable<TValue>(
24
+ value: any,
25
+ ): asserts value is AsyncIterable<TValue> {
26
+ if (!(Symbol.asyncIterator in value)) {
27
+ throw new Error('Expected AsyncIterable - are you using Node >= 18.0.0?');
28
+ }
29
+ }
32
30
 
33
31
  export async function nodeHTTPRequestHandler<
34
32
  TRouter extends AnyRouter,
@@ -38,11 +36,11 @@ export async function nodeHTTPRequestHandler<
38
36
  const handleViaMiddleware = opts.middleware ?? ((_req, _res, next) => next());
39
37
 
40
38
  return handleViaMiddleware(opts.req, opts.res, async (err) => {
41
- if (err) throw err;
39
+ const req = incomingMessageToRequest(opts.req, {
40
+ maxBodySize: opts.maxBodySize ?? null,
41
+ });
42
42
 
43
- //
44
43
  // Build tRPC dependencies
45
-
46
44
  const createContext: ResolveHTTPRequestOptionsContextFn<TRouter> = async (
47
45
  innerOpts,
48
46
  ) => {
@@ -52,109 +50,32 @@ export async function nodeHTTPRequestHandler<
52
50
  });
53
51
  };
54
52
 
55
- const query = opts.req.query
56
- ? new URLSearchParams(opts.req.query as any)
57
- : new URLSearchParams(opts.req.url!.split('?')[1]);
58
-
59
- const jsonContentTypeHandler =
60
- defaultJSONContentTypeHandler as unknown as NodeHTTPContentTypeHandler<
61
- TRequest,
62
- TResponse
63
- >;
64
-
65
- const contentTypeHandlers = opts.experimental_contentTypeHandlers ?? [
66
- jsonContentTypeHandler,
67
- ];
68
-
69
- const contentTypeHandler =
70
- contentTypeHandlers.find((handler) =>
71
- handler.isMatch({
72
- // FIXME: no typecasting should be needed here
73
- ...(opts as any),
74
- query,
75
- }),
76
- ) ??
77
- // fallback to json
78
- jsonContentTypeHandler;
79
-
80
- const bodyResult = await contentTypeHandler.getBody({
81
- // FIXME: no typecasting should be needed here
82
- ...(opts as any),
83
- query,
84
- });
85
-
86
- const req: HTTPRequest = {
87
- method: opts.req.method!,
88
- headers: opts.req.headers,
89
- query,
90
- body: bodyResult.ok ? bodyResult.data : undefined,
91
- };
92
-
93
- let isStream = false;
94
- let formatter: ReturnType<typeof getBatchStreamFormatter>;
95
- const unstable_onHead = (head: HTTPResponse, isStreaming: boolean) => {
96
- if (
97
- 'status' in head &&
98
- (!opts.res.statusCode || opts.res.statusCode === 200)
99
- ) {
100
- opts.res.statusCode = head.status;
101
- }
102
- for (const [key, value] of Object.entries(head.headers ?? {})) {
103
- /* istanbul ignore if -- @preserve */
104
- if (typeof value === 'undefined') {
105
- continue;
106
- }
107
- opts.res.setHeader(key, value);
108
- }
109
- if (isStreaming) {
110
- opts.res.setHeader('Transfer-Encoding', 'chunked');
111
- const vary = opts.res.getHeader('Vary');
112
- opts.res.setHeader(
113
- 'Vary',
114
- vary ? 'trpc-batch-mode, ' + vary : 'trpc-batch-mode',
115
- );
116
- isStream = true;
117
- formatter = getBatchStreamFormatter();
118
- opts.res.flushHeaders();
119
- }
120
- };
121
-
122
- const unstable_onChunk = ([index, string]: ResponseChunk) => {
123
- if (index === -1) {
124
- /**
125
- * Full response, no streaming. This can happen
126
- * - if the response is an error
127
- * - if response is empty (HEAD request)
128
- */
129
- opts.res.end(string);
130
- } else {
131
- opts.res.write(formatter!(index, string));
132
- opts.res.flush?.();
133
- }
134
- };
135
-
136
- await resolveHTTPResponse<TRouter, HTTPRequest>({
53
+ const response = await resolveResponse({
137
54
  ...opts,
138
55
  req,
56
+ error: err ? getTRPCErrorFromUnknown(err) : null,
139
57
  createContext,
140
- error: bodyResult.ok ? null : bodyResult.error,
141
- preprocessedBody: bodyResult.ok ? bodyResult.preprocessed : false,
142
58
  onError(o) {
143
59
  opts?.onError?.({
144
60
  ...o,
145
61
  req: opts.req,
146
62
  });
147
63
  },
148
- contentTypeHandler,
149
- unstable_onHead,
150
- unstable_onChunk,
151
64
  });
152
65
 
153
- if (isStream) {
154
- opts.res.write(formatter!.end());
155
- opts.res.end();
66
+ if (opts.res.statusCode === 200) {
67
+ // if the status code is set, we assume that it's been manually overridden
68
+ opts.res.statusCode = response.status;
156
69
  }
157
-
158
- return opts.res;
70
+ for (const [key, value] of response.headers) {
71
+ opts.res.setHeader(key, value);
72
+ }
73
+ if (response.body) {
74
+ assertAsyncIterable(response.body);
75
+ for await (const chunk of response.body) {
76
+ opts.res.write(chunk);
77
+ }
78
+ }
79
+ opts.res.end();
159
80
  });
160
81
  }
@@ -9,7 +9,11 @@
9
9
  */
10
10
  import type * as http from 'http';
11
11
  // @trpc/server
12
- import type { AnyRouter, inferRouterContext } from '../../@trpc/server';
12
+ import type {
13
+ AnyRouter,
14
+ CreateContextCallback,
15
+ inferRouterContext,
16
+ } from '../../@trpc/server';
13
17
  // @trpc/server/http
14
18
  import type {
15
19
  HTTPBaseHandlerOptions,
@@ -17,7 +21,6 @@ import type {
17
21
  } from '../../@trpc/server/http';
18
22
  // eslint-disable-next-line no-restricted-imports
19
23
  import type { MaybePromise } from '../../unstable-core-do-not-import';
20
- import type { NodeHTTPContentTypeHandler } from './internals/contentType';
21
24
 
22
25
  interface ParsedQs {
23
26
  [key: string]: ParsedQs | ParsedQs[] | string[] | string | undefined;
@@ -43,19 +46,10 @@ export type NodeHTTPCreateContextOption<
43
46
  TRouter extends AnyRouter,
44
47
  TRequest,
45
48
  TResponse,
46
- > = object extends inferRouterContext<TRouter>
47
- ? {
48
- /**
49
- * @link https://trpc.io/docs/v11/context
50
- **/
51
- createContext?: NodeHTTPCreateContextFn<TRouter, TRequest, TResponse>;
52
- }
53
- : {
54
- /**
55
- * @link https://trpc.io/docs/v11/context
56
- **/
57
- createContext: NodeHTTPCreateContextFn<TRouter, TRequest, TResponse>;
58
- };
49
+ > = CreateContextCallback<
50
+ inferRouterContext<TRouter>,
51
+ NodeHTTPCreateContextFn<TRouter, TRequest, TResponse>
52
+ >;
59
53
 
60
54
  /**
61
55
  * @internal
@@ -89,10 +83,6 @@ export type NodeHTTPHandlerOptions<
89
83
  */
90
84
  middleware?: ConnectMiddleware;
91
85
  maxBodySize?: number;
92
- experimental_contentTypeHandlers?: NodeHTTPContentTypeHandler<
93
- TRequest,
94
- TResponse
95
- >[];
96
86
  };
97
87
 
98
88
  export type NodeHTTPRequestHandlerOptions<
@@ -37,8 +37,7 @@ export function createHTTPHandler<TRouter extends AnyRouter>(
37
37
  const path = url.pathname.slice(1);
38
38
 
39
39
  await nodeHTTPRequestHandler({
40
- // FIXME: no typecasting should be needed here
41
- ...(opts as CreateHTTPHandlerOptions<AnyRouter>),
40
+ ...(opts as any),
42
41
  req,
43
42
  res,
44
43
  path,
@@ -1,6 +1,10 @@
1
1
  import type { IncomingMessage } from 'http';
2
2
  import type ws from 'ws';
3
- import type { AnyRouter, inferRouterContext } from '../@trpc/server';
3
+ import type {
4
+ AnyRouter,
5
+ CreateContextCallback,
6
+ inferRouterContext,
7
+ } from '../@trpc/server';
4
8
  import {
5
9
  callProcedure,
6
10
  getErrorShape,
@@ -46,19 +50,10 @@ export type CreateWSSContextFn<TRouter extends AnyRouter> = (
46
50
 
47
51
  export type WSConnectionHandlerOptions<TRouter extends AnyRouter> =
48
52
  BaseHandlerOptions<TRouter, IncomingMessage> &
49
- (object extends inferRouterContext<TRouter>
50
- ? {
51
- /**
52
- * @link https://trpc.io/docs/v11/context
53
- **/
54
- createContext?: CreateWSSContextFn<TRouter>;
55
- }
56
- : {
57
- /**
58
- * @link https://trpc.io/docs/v11/context
59
- **/
60
- createContext: CreateWSSContextFn<TRouter>;
61
- });
53
+ CreateContextCallback<
54
+ inferRouterContext<TRouter>,
55
+ CreateWSSContextFn<TRouter>
56
+ >;
62
57
 
63
58
  /**
64
59
  * Web socket server handler