@trpc/server 11.0.0-rc.361 → 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.
- package/dist/@trpc/server/http.d.ts +7 -5
- package/dist/@trpc/server/http.d.ts.map +1 -1
- package/dist/@trpc/server/index.d.ts +1 -2
- package/dist/@trpc/server/index.d.ts.map +1 -1
- package/dist/adapters/aws-lambda/getPlanner.d.ts +13 -0
- package/dist/adapters/aws-lambda/getPlanner.d.ts.map +1 -0
- package/dist/adapters/aws-lambda/getPlanner.js +143 -0
- package/dist/adapters/aws-lambda/getPlanner.mjs +141 -0
- package/dist/adapters/aws-lambda/index.d.ts +12 -9
- package/dist/adapters/aws-lambda/index.d.ts.map +1 -1
- package/dist/adapters/aws-lambda/index.js +7 -76
- package/dist/adapters/aws-lambda/index.mjs +9 -72
- package/dist/adapters/express.js +1 -0
- package/dist/adapters/express.mjs +1 -0
- package/dist/adapters/fastify/fastifyRequestHandler.d.ts +19 -2
- package/dist/adapters/fastify/fastifyRequestHandler.d.ts.map +1 -1
- package/dist/adapters/fastify/fastifyRequestHandler.js +12 -63
- package/dist/adapters/fastify/fastifyRequestHandler.mjs +13 -64
- package/dist/adapters/fastify/fastifyTRPCPlugin.d.ts +1 -1
- package/dist/adapters/fastify/fastifyTRPCPlugin.d.ts.map +1 -1
- package/dist/adapters/fetch/fetchRequestHandler.d.ts +2 -2
- package/dist/adapters/fetch/fetchRequestHandler.d.ts.map +1 -1
- package/dist/adapters/fetch/fetchRequestHandler.js +28 -85
- package/dist/adapters/fetch/fetchRequestHandler.mjs +29 -86
- package/dist/adapters/fetch/types.d.ts +2 -2
- package/dist/adapters/fetch/types.d.ts.map +1 -1
- package/dist/adapters/next.js +1 -1
- package/dist/adapters/next.mjs +1 -1
- package/dist/adapters/node-http/incomingMessageToRequest.d.ts +18 -0
- package/dist/adapters/node-http/incomingMessageToRequest.d.ts.map +1 -0
- package/dist/adapters/node-http/incomingMessageToRequest.js +71 -0
- package/dist/adapters/node-http/incomingMessageToRequest.mjs +69 -0
- package/dist/adapters/node-http/index.d.ts +1 -0
- package/dist/adapters/node-http/index.d.ts.map +1 -1
- package/dist/adapters/node-http/index.js +2 -0
- package/dist/adapters/node-http/index.mjs +1 -0
- package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts +1 -1
- package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts.map +1 -1
- package/dist/adapters/node-http/nodeHTTPRequestHandler.js +27 -70
- package/dist/adapters/node-http/nodeHTTPRequestHandler.mjs +28 -71
- package/dist/adapters/node-http/types.d.ts +7 -8
- package/dist/adapters/node-http/types.d.ts.map +1 -1
- package/dist/adapters/ws.js +1 -1
- package/dist/adapters/ws.mjs +1 -1
- package/dist/bundle-analysis.json +180 -277
- package/dist/http.js +4 -2
- package/dist/http.mjs +2 -1
- package/dist/index.js +2 -4
- package/dist/index.mjs +1 -2
- package/dist/unstable-core-do-not-import/http/contentType.d.ts +8 -20
- package/dist/unstable-core-do-not-import/http/contentType.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/contentType.js +180 -0
- package/dist/unstable-core-do-not-import/http/contentType.mjs +178 -0
- package/dist/unstable-core-do-not-import/http/contentTypeParsers.d.ts +14 -0
- package/dist/unstable-core-do-not-import/http/contentTypeParsers.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/http/contentTypeParsers.js +14 -0
- package/dist/unstable-core-do-not-import/http/contentTypeParsers.mjs +12 -0
- package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.d.ts +1 -1
- package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/resolveHTTPResponse.d.ts +7 -43
- package/dist/unstable-core-do-not-import/http/resolveHTTPResponse.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/resolveHTTPResponse.js +119 -134
- package/dist/unstable-core-do-not-import/http/resolveHTTPResponse.mjs +119 -134
- package/dist/unstable-core-do-not-import/http/types.d.ts +25 -27
- package/dist/unstable-core-do-not-import/http/types.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/initTRPC.d.ts +1 -1
- package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +1 -3
- package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/procedureBuilder.js +0 -2
- package/dist/unstable-core-do-not-import/procedureBuilder.mjs +1 -2
- package/dist/unstable-core-do-not-import/rootConfig.d.ts +0 -9
- package/dist/unstable-core-do-not-import/rootConfig.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/utils.d.ts +3 -0
- package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/utils.js +2 -0
- package/dist/unstable-core-do-not-import/utils.mjs +2 -1
- package/dist/unstable-core-do-not-import.d.ts +9 -3
- package/dist/unstable-core-do-not-import.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import.js +11 -7
- package/dist/unstable-core-do-not-import.mjs +7 -5
- package/package.json +3 -13
- package/src/@trpc/server/http.ts +7 -12
- package/src/@trpc/server/index.ts +0 -3
- package/src/adapters/aws-lambda/getPlanner.ts +191 -0
- package/src/adapters/aws-lambda/index.ts +43 -107
- package/src/adapters/express.ts +1 -1
- package/src/adapters/fastify/fastifyRequestHandler.ts +40 -89
- package/src/adapters/fastify/fastifyTRPCPlugin.ts +1 -1
- package/src/adapters/fetch/fetchRequestHandler.ts +35 -111
- package/src/adapters/fetch/types.ts +4 -2
- package/src/adapters/next.ts +1 -1
- package/src/adapters/node-http/incomingMessageToRequest.ts +94 -0
- package/src/adapters/node-http/index.ts +1 -0
- package/src/adapters/node-http/nodeHTTPRequestHandler.ts +31 -97
- package/src/adapters/node-http/types.ts +27 -37
- package/src/adapters/standalone.ts +1 -1
- package/src/unstable-core-do-not-import/http/contentType.ts +214 -22
- package/src/unstable-core-do-not-import/http/contentTypeParsers.ts +29 -0
- package/src/unstable-core-do-not-import/http/getHTTPStatusCode.ts +2 -2
- package/src/unstable-core-do-not-import/http/resolveHTTPResponse.ts +135 -210
- package/src/unstable-core-do-not-import/http/types.ts +25 -30
- package/src/unstable-core-do-not-import/procedureBuilder.ts +2 -4
- package/src/unstable-core-do-not-import/rootConfig.ts +0 -10
- package/src/unstable-core-do-not-import/utils.ts +4 -0
- package/src/unstable-core-do-not-import.ts +9 -3
- package/adapters/node-http/content-type/form-data/index.d.ts +0 -1
- package/adapters/node-http/content-type/form-data/index.js +0 -1
- package/adapters/node-http/content-type/json/index.d.ts +0 -1
- package/adapters/node-http/content-type/json/index.js +0 -1
- package/dist/adapters/aws-lambda/content-type/json/index.d.ts +0 -10
- package/dist/adapters/aws-lambda/content-type/json/index.d.ts.map +0 -1
- package/dist/adapters/aws-lambda/content-type/json/index.js +0 -62
- package/dist/adapters/aws-lambda/content-type/json/index.mjs +0 -60
- package/dist/adapters/aws-lambda/utils.d.ts +0 -31
- package/dist/adapters/aws-lambda/utils.d.ts.map +0 -1
- package/dist/adapters/aws-lambda/utils.js +0 -111
- package/dist/adapters/aws-lambda/utils.mjs +0 -103
- package/dist/adapters/content-handlers/concurrentCache.d.ts +0 -7
- package/dist/adapters/content-handlers/concurrentCache.d.ts.map +0 -1
- package/dist/adapters/content-handlers/concurrentCache.js +0 -17
- package/dist/adapters/content-handlers/concurrentCache.mjs +0 -15
- package/dist/adapters/content-handlers/selectContentHandlerOrUnsupportedMediaType.d.ts +0 -10
- package/dist/adapters/content-handlers/selectContentHandlerOrUnsupportedMediaType.d.ts.map +0 -1
- package/dist/adapters/content-handlers/selectContentHandlerOrUnsupportedMediaType.js +0 -33
- package/dist/adapters/content-handlers/selectContentHandlerOrUnsupportedMediaType.mjs +0 -31
- package/dist/adapters/fastify/content-type/json/index.d.ts +0 -8
- package/dist/adapters/fastify/content-type/json/index.d.ts.map +0 -1
- package/dist/adapters/fastify/content-type/json/index.js +0 -62
- package/dist/adapters/fastify/content-type/json/index.mjs +0 -60
- package/dist/adapters/fastify/types.d.ts +0 -11
- package/dist/adapters/fastify/types.d.ts.map +0 -1
- package/dist/adapters/fetch/content-type/json/index.d.ts +0 -9
- package/dist/adapters/fetch/content-type/json/index.d.ts.map +0 -1
- package/dist/adapters/fetch/content-type/json/index.js +0 -55
- package/dist/adapters/fetch/content-type/json/index.mjs +0 -53
- package/dist/adapters/node-http/content-type/form-data/index.d.ts +0 -5
- package/dist/adapters/node-http/content-type/form-data/index.d.ts.map +0 -1
- package/dist/adapters/node-http/content-type/form-data/index.js +0 -32
- package/dist/adapters/node-http/content-type/form-data/index.mjs +0 -30
- package/dist/adapters/node-http/content-type/json/getPostBody.d.ts +0 -7
- package/dist/adapters/node-http/content-type/json/getPostBody.d.ts.map +0 -1
- package/dist/adapters/node-http/content-type/json/getPostBody.js +0 -45
- package/dist/adapters/node-http/content-type/json/getPostBody.mjs +0 -43
- package/dist/adapters/node-http/content-type/json/index.d.ts +0 -5
- package/dist/adapters/node-http/content-type/json/index.d.ts.map +0 -1
- package/dist/adapters/node-http/content-type/json/index.js +0 -68
- package/dist/adapters/node-http/content-type/json/index.mjs +0 -66
- package/dist/adapters/node-http/content-type/octet/index.d.ts +0 -5
- package/dist/adapters/node-http/content-type/octet/index.d.ts.map +0 -1
- package/dist/adapters/node-http/content-type/octet/index.js +0 -19
- package/dist/adapters/node-http/content-type/octet/index.mjs +0 -17
- package/dist/adapters/node-http/content-type/types.d.ts +0 -8
- package/dist/adapters/node-http/content-type/types.d.ts.map +0 -1
- package/dist/unstable-core-do-not-import/contentTypeParsers.d.ts +0 -16
- package/dist/unstable-core-do-not-import/contentTypeParsers.d.ts.map +0 -1
- package/dist/unstable-core-do-not-import/contentTypeParsers.js +0 -23
- package/dist/unstable-core-do-not-import/contentTypeParsers.mjs +0 -21
- package/dist/unstable-core-do-not-import/http/index.d.ts +0 -11
- package/dist/unstable-core-do-not-import/http/index.d.ts.map +0 -1
- package/src/adapters/aws-lambda/content-type/json/index.ts +0 -108
- package/src/adapters/aws-lambda/utils.ts +0 -170
- package/src/adapters/content-handlers/concurrentCache.ts +0 -16
- package/src/adapters/content-handlers/selectContentHandlerOrUnsupportedMediaType.ts +0 -45
- package/src/adapters/fastify/content-type/json/index.ts +0 -106
- package/src/adapters/fastify/types.ts +0 -22
- package/src/adapters/fetch/content-type/json/index.ts +0 -90
- package/src/adapters/node-http/content-type/form-data/index.ts +0 -37
- package/src/adapters/node-http/content-type/json/getPostBody.ts +0 -49
- package/src/adapters/node-http/content-type/json/index.ts +0 -100
- package/src/adapters/node-http/content-type/octet/index.ts +0 -27
- package/src/adapters/node-http/content-type/types.ts +0 -19
- package/src/unstable-core-do-not-import/contentTypeParsers.ts +0 -37
- package/src/unstable-core-do-not-import/http/index.ts +0 -28
|
@@ -7,23 +7,36 @@
|
|
|
7
7
|
* import type { HTTPBaseHandlerOptions } from '@trpc/server/http'
|
|
8
8
|
* ```
|
|
9
9
|
*/
|
|
10
|
-
import { Readable } from 'stream';
|
|
11
10
|
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
12
11
|
// @trpc/server
|
|
13
12
|
import type { AnyRouter } from '../../@trpc/server';
|
|
14
13
|
import type {
|
|
15
|
-
|
|
16
|
-
HTTPResponse,
|
|
14
|
+
HTTPBaseHandlerOptions,
|
|
17
15
|
ResolveHTTPRequestOptionsContextFn,
|
|
18
|
-
ResponseChunk,
|
|
19
16
|
} from '../../@trpc/server/http';
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
|
|
17
|
+
import { resolveResponse } from '../../@trpc/server/http';
|
|
18
|
+
import type {
|
|
19
|
+
IncomingMessageWithBody,
|
|
20
|
+
NodeHTTPCreateContextOption,
|
|
21
|
+
} from '../node-http';
|
|
22
|
+
import { incomingMessageToRequest } from '../node-http';
|
|
23
|
+
|
|
24
|
+
export type FastifyHandlerOptions<
|
|
25
|
+
TRouter extends AnyRouter,
|
|
26
|
+
TRequest extends FastifyRequest,
|
|
27
|
+
TResponse extends FastifyReply,
|
|
28
|
+
> = HTTPBaseHandlerOptions<TRouter, TRequest> &
|
|
29
|
+
NodeHTTPCreateContextOption<TRouter, TRequest, TResponse>;
|
|
30
|
+
|
|
31
|
+
type FastifyRequestHandlerOptions<
|
|
32
|
+
TRouter extends AnyRouter,
|
|
33
|
+
TRequest extends FastifyRequest,
|
|
34
|
+
TResponse extends FastifyReply,
|
|
35
|
+
> = FastifyHandlerOptions<TRouter, TRequest, TResponse> & {
|
|
36
|
+
req: TRequest;
|
|
37
|
+
res: TResponse;
|
|
38
|
+
path: string;
|
|
39
|
+
};
|
|
27
40
|
|
|
28
41
|
export async function fastifyRequestHandler<
|
|
29
42
|
TRouter extends AnyRouter,
|
|
@@ -39,90 +52,28 @@ export async function fastifyRequestHandler<
|
|
|
39
52
|
});
|
|
40
53
|
};
|
|
41
54
|
|
|
42
|
-
const
|
|
43
|
-
? new URLSearchParams(opts.req.query as any)
|
|
44
|
-
: new URLSearchParams(opts.req.url.split('?')[1]);
|
|
55
|
+
const incomingMessage = opts.req.raw as IncomingMessageWithBody;
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const promise = new Promise<FastifyReply>((r) => (resolve = r));
|
|
54
|
-
|
|
55
|
-
let isStream = false;
|
|
56
|
-
let stream: Readable;
|
|
57
|
-
let formatter: ReturnType<typeof getBatchStreamFormatter>;
|
|
58
|
-
const unstable_onHead = (head: HTTPResponse, isStreaming: boolean) => {
|
|
59
|
-
if (!opts.res.statusCode || opts.res.statusCode === 200) {
|
|
60
|
-
opts.res.statusCode = head.status;
|
|
61
|
-
}
|
|
62
|
-
for (const [key, value] of Object.entries(head.headers ?? {})) {
|
|
63
|
-
/* istanbul ignore if -- @preserve */
|
|
64
|
-
if (typeof value === 'undefined') {
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
void opts.res.header(key, value);
|
|
68
|
-
}
|
|
69
|
-
if (isStreaming) {
|
|
70
|
-
void opts.res.header('Transfer-Encoding', 'chunked');
|
|
71
|
-
void opts.res.header(
|
|
72
|
-
'Vary',
|
|
73
|
-
opts.res.hasHeader('Vary')
|
|
74
|
-
? 'trpc-batch-mode, ' + opts.res.getHeader('Vary')
|
|
75
|
-
: 'trpc-batch-mode',
|
|
76
|
-
);
|
|
77
|
-
stream = new Readable();
|
|
78
|
-
stream._read = () => {}; // eslint-disable-line @typescript-eslint/no-empty-function -- https://github.com/fastify/fastify/issues/805#issuecomment-369172154
|
|
79
|
-
resolve(opts.res.send(stream));
|
|
80
|
-
isStream = true;
|
|
81
|
-
formatter = getBatchStreamFormatter();
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const unstable_onChunk = ([index, string]: ResponseChunk) => {
|
|
86
|
-
if (index === -1) {
|
|
87
|
-
// full response, no streaming
|
|
88
|
-
resolve(opts.res.send(string));
|
|
89
|
-
} else {
|
|
90
|
-
stream.push(formatter(index, string));
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const [contentTypeHandler, unsupportedMediaTypeError] =
|
|
95
|
-
selectContentHandlerOrUnsupportedMediaType(
|
|
96
|
-
[getFastifyHTTPJSONContentTypeHandler<TRouter, TRequest, TResponse>()],
|
|
97
|
-
opts,
|
|
98
|
-
);
|
|
57
|
+
// monkey-path body to the IncomingMessage
|
|
58
|
+
if ('body' in opts.req) {
|
|
59
|
+
incomingMessage.body = opts.req.body;
|
|
60
|
+
}
|
|
61
|
+
const req = incomingMessageToRequest(incomingMessage, {
|
|
62
|
+
maxBodySize: null,
|
|
63
|
+
});
|
|
99
64
|
|
|
100
|
-
|
|
65
|
+
const res = await resolveResponse({
|
|
101
66
|
...opts,
|
|
102
67
|
req,
|
|
103
|
-
error:
|
|
104
|
-
async getInput(info) {
|
|
105
|
-
return await contentTypeHandler?.getInputs(opts, info);
|
|
106
|
-
},
|
|
68
|
+
error: null,
|
|
107
69
|
createContext,
|
|
108
|
-
|
|
109
70
|
onError(o) {
|
|
110
|
-
opts?.onError?.({
|
|
71
|
+
opts?.onError?.({
|
|
72
|
+
...o,
|
|
73
|
+
req: opts.req,
|
|
74
|
+
});
|
|
111
75
|
},
|
|
112
|
-
|
|
113
|
-
unstable_onChunk,
|
|
114
|
-
})
|
|
115
|
-
.then(() => {
|
|
116
|
-
if (isStream) {
|
|
117
|
-
stream.push(formatter.end());
|
|
118
|
-
stream.push(null); // https://github.com/fastify/fastify/issues/805#issuecomment-369172154
|
|
119
|
-
}
|
|
120
|
-
})
|
|
121
|
-
.catch(() => {
|
|
122
|
-
if (isStream) {
|
|
123
|
-
stream.push(null);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
76
|
+
});
|
|
126
77
|
|
|
127
|
-
|
|
78
|
+
await opts.res.send(res);
|
|
128
79
|
}
|
|
@@ -14,8 +14,8 @@ import type { AnyRouter } from '../../@trpc/server';
|
|
|
14
14
|
import type { NodeHTTPCreateContextFnOptions } from '../node-http';
|
|
15
15
|
import type { WSSHandlerOptions } from '../ws';
|
|
16
16
|
import { getWSConnectionHandler } from '../ws';
|
|
17
|
+
import type { FastifyHandlerOptions } from './fastifyRequestHandler';
|
|
17
18
|
import { fastifyRequestHandler } from './fastifyRequestHandler';
|
|
18
|
-
import type { FastifyHandlerOptions } from './types';
|
|
19
19
|
|
|
20
20
|
export interface FastifyTRPCPluginOptions<TRouter extends AnyRouter> {
|
|
21
21
|
prefix?: string;
|
|
@@ -10,20 +10,9 @@
|
|
|
10
10
|
// @trpc/server
|
|
11
11
|
|
|
12
12
|
import type { AnyRouter } from '../../@trpc/server';
|
|
13
|
-
import type {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
ResolveHTTPRequestOptionsContextFn,
|
|
17
|
-
ResponseChunk,
|
|
18
|
-
} from '../../@trpc/server/http';
|
|
19
|
-
import {
|
|
20
|
-
getBatchStreamFormatter,
|
|
21
|
-
resolveHTTPResponse,
|
|
22
|
-
toURL,
|
|
23
|
-
} from '../../@trpc/server/http';
|
|
24
|
-
import { selectContentHandlerOrUnsupportedMediaType } from '../content-handlers/selectContentHandlerOrUnsupportedMediaType';
|
|
25
|
-
import { getFetchHTTPJSONContentTypeHandler } from './content-type/json';
|
|
26
|
-
import type { FetchHandlerOptions } from './types';
|
|
13
|
+
import type { ResolveHTTPRequestOptionsContextFn } from '../../@trpc/server/http';
|
|
14
|
+
import { resolveResponse, toURL } from '../../@trpc/server/http';
|
|
15
|
+
import type { FetchHandlerRequestOptions } from './types';
|
|
27
16
|
|
|
28
17
|
const trimSlashes = (path: string): string => {
|
|
29
18
|
path = path.startsWith('/') ? path.slice(1) : path;
|
|
@@ -33,7 +22,7 @@ const trimSlashes = (path: string): string => {
|
|
|
33
22
|
};
|
|
34
23
|
|
|
35
24
|
export async function fetchRequestHandler<TRouter extends AnyRouter>(
|
|
36
|
-
opts:
|
|
25
|
+
opts: FetchHandlerRequestOptions<TRouter>,
|
|
37
26
|
): Promise<Response> {
|
|
38
27
|
const resHeaders = new Headers();
|
|
39
28
|
|
|
@@ -49,108 +38,43 @@ export async function fetchRequestHandler<TRouter extends AnyRouter>(
|
|
|
49
38
|
const endpoint = trimSlashes(opts.endpoint);
|
|
50
39
|
const path = trimSlashes(pathname.slice(endpoint.length));
|
|
51
40
|
|
|
52
|
-
|
|
53
|
-
query: url.searchParams,
|
|
54
|
-
method: opts.req.method,
|
|
55
|
-
headers: Object.fromEntries(opts.req.headers),
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
let resolve: (value: Response) => void;
|
|
59
|
-
const promise = new Promise<Response>((r) => (resolve = r));
|
|
60
|
-
let status = 200;
|
|
61
|
-
|
|
62
|
-
let isStream = false;
|
|
63
|
-
let controller: ReadableStreamController<any>;
|
|
64
|
-
let encoder: TextEncoder;
|
|
65
|
-
let formatter: ReturnType<typeof getBatchStreamFormatter>;
|
|
66
|
-
const unstable_onHead = (head: HTTPResponse, isStreaming: boolean) => {
|
|
67
|
-
for (const [key, value] of Object.entries(head.headers ?? {})) {
|
|
68
|
-
/* istanbul ignore if -- @preserve */
|
|
69
|
-
if (typeof value === 'undefined') {
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (typeof value === 'string') {
|
|
73
|
-
resHeaders.set(key, value);
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
for (const v of value) {
|
|
77
|
-
resHeaders.append(key, v);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
status = head.status;
|
|
81
|
-
if (isStreaming) {
|
|
82
|
-
resHeaders.set('Transfer-Encoding', 'chunked');
|
|
83
|
-
resHeaders.append('Vary', 'trpc-batch-mode');
|
|
84
|
-
const stream = new ReadableStream({
|
|
85
|
-
start(c) {
|
|
86
|
-
controller = c;
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
const response = new Response(stream, {
|
|
90
|
-
status,
|
|
91
|
-
headers: resHeaders,
|
|
92
|
-
});
|
|
93
|
-
resolve(response);
|
|
94
|
-
encoder = new TextEncoder();
|
|
95
|
-
formatter = getBatchStreamFormatter();
|
|
96
|
-
isStream = true;
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const unstable_onChunk = ([index, string]: ResponseChunk) => {
|
|
101
|
-
if (index === -1) {
|
|
102
|
-
// full response, no streaming
|
|
103
|
-
const response = new Response(string || null, {
|
|
104
|
-
status,
|
|
105
|
-
headers: resHeaders,
|
|
106
|
-
});
|
|
107
|
-
resolve(response);
|
|
108
|
-
} else {
|
|
109
|
-
controller.enqueue(encoder.encode(formatter(index, string)));
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
const [contentTypeHandler, unsupportedMediaTypeError] =
|
|
114
|
-
selectContentHandlerOrUnsupportedMediaType(
|
|
115
|
-
[getFetchHTTPJSONContentTypeHandler<TRouter>()],
|
|
116
|
-
{
|
|
117
|
-
...opts,
|
|
118
|
-
url,
|
|
119
|
-
},
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
resolveHTTPResponse({
|
|
41
|
+
return await resolveResponse({
|
|
123
42
|
...opts,
|
|
124
|
-
req,
|
|
43
|
+
req: opts.req,
|
|
125
44
|
createContext,
|
|
126
45
|
path,
|
|
127
|
-
error:
|
|
128
|
-
async getInput(info) {
|
|
129
|
-
return await contentTypeHandler?.getInputs(
|
|
130
|
-
{
|
|
131
|
-
...opts,
|
|
132
|
-
url,
|
|
133
|
-
},
|
|
134
|
-
info,
|
|
135
|
-
);
|
|
136
|
-
},
|
|
46
|
+
error: null,
|
|
137
47
|
onError(o) {
|
|
138
48
|
opts?.onError?.({ ...o, req: opts.req });
|
|
139
49
|
},
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
+
}
|
|
152
72
|
}
|
|
153
|
-
});
|
|
154
73
|
|
|
155
|
-
|
|
74
|
+
return {
|
|
75
|
+
headers: resHeaders,
|
|
76
|
+
status: meta?.status,
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
});
|
|
156
80
|
}
|
|
@@ -12,7 +12,6 @@ import type {
|
|
|
12
12
|
AnyRouter,
|
|
13
13
|
CreateContextCallback,
|
|
14
14
|
inferRouterContext,
|
|
15
|
-
WrapCreateContext,
|
|
16
15
|
} from '../../@trpc/server';
|
|
17
16
|
// @trpc/server/http
|
|
18
17
|
import type {
|
|
@@ -45,7 +44,10 @@ export type FetchHandlerOptions<TRouter extends AnyRouter> =
|
|
|
45
44
|
|
|
46
45
|
export type FetchHandlerRequestOptions<TRouter extends AnyRouter> =
|
|
47
46
|
HTTPBaseHandlerOptions<TRouter, Request> &
|
|
48
|
-
|
|
47
|
+
CreateContextCallback<
|
|
48
|
+
inferRouterContext<TRouter>,
|
|
49
|
+
FetchCreateContextFn<TRouter>
|
|
50
|
+
> & {
|
|
49
51
|
req: Request;
|
|
50
52
|
endpoint: string;
|
|
51
53
|
};
|
package/src/adapters/next.ts
CHANGED
|
@@ -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
|
+
}
|
|
@@ -7,30 +7,27 @@
|
|
|
7
7
|
* import type { HTTPBaseHandlerOptions } from '@trpc/server/http'
|
|
8
8
|
* ```
|
|
9
9
|
*/
|
|
10
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
11
10
|
|
|
12
11
|
// @trpc/server
|
|
13
|
-
|
|
14
|
-
import type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
ResponseChunk,
|
|
19
|
-
} from '../../@trpc/server/http';
|
|
20
|
-
import {
|
|
21
|
-
getBatchStreamFormatter,
|
|
22
|
-
resolveHTTPResponse,
|
|
23
|
-
} from '../../@trpc/server/http';
|
|
24
|
-
import { selectContentHandlerOrUnsupportedMediaType } from '../content-handlers/selectContentHandlerOrUnsupportedMediaType';
|
|
25
|
-
import { getFormDataContentTypeHandler } from './content-type/form-data';
|
|
26
|
-
import { getNodeHTTPJSONContentTypeHandler } from './content-type/json';
|
|
27
|
-
import { getOctetContentTypeHandler } from './content-type/octet';
|
|
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';
|
|
28
17
|
import type {
|
|
29
18
|
NodeHTTPRequest,
|
|
30
19
|
NodeHTTPRequestHandlerOptions,
|
|
31
20
|
NodeHTTPResponse,
|
|
32
21
|
} from './types';
|
|
33
22
|
|
|
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
|
+
}
|
|
30
|
+
|
|
34
31
|
export async function nodeHTTPRequestHandler<
|
|
35
32
|
TRouter extends AnyRouter,
|
|
36
33
|
TRequest extends NodeHTTPRequest,
|
|
@@ -39,11 +36,11 @@ export async function nodeHTTPRequestHandler<
|
|
|
39
36
|
const handleViaMiddleware = opts.middleware ?? ((_req, _res, next) => next());
|
|
40
37
|
|
|
41
38
|
return handleViaMiddleware(opts.req, opts.res, async (err) => {
|
|
42
|
-
|
|
39
|
+
const req = incomingMessageToRequest(opts.req, {
|
|
40
|
+
maxBodySize: opts.maxBodySize ?? null,
|
|
41
|
+
});
|
|
43
42
|
|
|
44
|
-
//
|
|
45
43
|
// Build tRPC dependencies
|
|
46
|
-
|
|
47
44
|
const createContext: ResolveHTTPRequestOptionsContextFn<TRouter> = async (
|
|
48
45
|
innerOpts,
|
|
49
46
|
) => {
|
|
@@ -53,95 +50,32 @@ export async function nodeHTTPRequestHandler<
|
|
|
53
50
|
});
|
|
54
51
|
};
|
|
55
52
|
|
|
56
|
-
const
|
|
57
|
-
? new URLSearchParams(opts.req.query as any)
|
|
58
|
-
: new URLSearchParams(opts.req.url!.split('?')[1]);
|
|
59
|
-
|
|
60
|
-
const req: HTTPRequest = {
|
|
61
|
-
method: opts.req.method!,
|
|
62
|
-
headers: opts.req.headers,
|
|
63
|
-
query,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
let isStream = false;
|
|
67
|
-
let formatter: ReturnType<typeof getBatchStreamFormatter>;
|
|
68
|
-
const unstable_onHead = (head: HTTPResponse, isStreaming: boolean) => {
|
|
69
|
-
if (
|
|
70
|
-
'status' in head &&
|
|
71
|
-
(!opts.res.statusCode || opts.res.statusCode === 200)
|
|
72
|
-
) {
|
|
73
|
-
opts.res.statusCode = head.status;
|
|
74
|
-
}
|
|
75
|
-
for (const [key, value] of Object.entries(head.headers ?? {})) {
|
|
76
|
-
/* istanbul ignore if -- @preserve */
|
|
77
|
-
if (typeof value === 'undefined') {
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
opts.res.setHeader(key, value);
|
|
81
|
-
}
|
|
82
|
-
if (isStreaming) {
|
|
83
|
-
opts.res.setHeader('Transfer-Encoding', 'chunked');
|
|
84
|
-
const vary = opts.res.getHeader('Vary');
|
|
85
|
-
opts.res.setHeader(
|
|
86
|
-
'Vary',
|
|
87
|
-
vary ? 'trpc-batch-mode, ' + vary : 'trpc-batch-mode',
|
|
88
|
-
);
|
|
89
|
-
isStream = true;
|
|
90
|
-
formatter = getBatchStreamFormatter();
|
|
91
|
-
opts.res.flushHeaders();
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const unstable_onChunk = ([index, string]: ResponseChunk) => {
|
|
96
|
-
if (index === -1) {
|
|
97
|
-
/**
|
|
98
|
-
* Full response, no streaming. This can happen
|
|
99
|
-
* - if the response is an error
|
|
100
|
-
* - if response is empty (HEAD request)
|
|
101
|
-
*/
|
|
102
|
-
opts.res.end(string);
|
|
103
|
-
} else {
|
|
104
|
-
opts.res.write(formatter!(index, string));
|
|
105
|
-
opts.res.flush?.();
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const [contentTypeHandler, unsupportedMediaTypeError] =
|
|
110
|
-
selectContentHandlerOrUnsupportedMediaType(
|
|
111
|
-
[
|
|
112
|
-
getNodeHTTPJSONContentTypeHandler<TRouter, TRequest, TResponse>(),
|
|
113
|
-
getFormDataContentTypeHandler<TRouter, TRequest, TResponse>(),
|
|
114
|
-
getOctetContentTypeHandler<TRouter, TRequest, TResponse>(),
|
|
115
|
-
],
|
|
116
|
-
{ ...opts, query },
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
await resolveHTTPResponse<TRouter, HTTPRequest>({
|
|
53
|
+
const response = await resolveResponse({
|
|
120
54
|
...opts,
|
|
121
55
|
req,
|
|
56
|
+
error: err ? getTRPCErrorFromUnknown(err) : null,
|
|
122
57
|
createContext,
|
|
123
|
-
error: unsupportedMediaTypeError,
|
|
124
58
|
onError(o) {
|
|
125
59
|
opts?.onError?.({
|
|
126
60
|
...o,
|
|
127
61
|
req: opts.req,
|
|
128
62
|
});
|
|
129
63
|
},
|
|
130
|
-
async getInput(inputsOpts) {
|
|
131
|
-
return await contentTypeHandler?.getInputs(
|
|
132
|
-
{ ...opts, query },
|
|
133
|
-
inputsOpts,
|
|
134
|
-
);
|
|
135
|
-
},
|
|
136
|
-
unstable_onHead,
|
|
137
|
-
unstable_onChunk,
|
|
138
64
|
});
|
|
139
65
|
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
opts.res.
|
|
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;
|
|
143
69
|
}
|
|
144
|
-
|
|
145
|
-
|
|
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();
|
|
146
80
|
});
|
|
147
81
|
}
|