@trpc/server 11.0.0-rc.417 → 11.0.0-rc.419
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/index.d.ts +1 -1
- package/dist/@trpc/server/index.d.ts.map +1 -1
- package/dist/adapters/aws-lambda/getPlanner.d.ts.map +1 -1
- package/dist/adapters/next-app-dir/redirect.d.ts.map +1 -1
- package/dist/adapters/node-http/incomingMessageToRequest.d.ts +0 -1
- package/dist/adapters/node-http/incomingMessageToRequest.d.ts.map +1 -1
- package/dist/adapters/node-http/incomingMessageToRequest.js +3 -1
- package/dist/adapters/node-http/incomingMessageToRequest.mjs +3 -1
- package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts.map +1 -1
- package/dist/adapters/node-http/nodeHTTPRequestHandler.js +30 -7
- package/dist/adapters/node-http/nodeHTTPRequestHandler.mjs +30 -7
- package/dist/adapters/node-http/types.d.ts +0 -1
- package/dist/adapters/node-http/types.d.ts.map +1 -1
- package/dist/adapters/standalone.d.ts +0 -1
- package/dist/adapters/standalone.d.ts.map +1 -1
- package/dist/adapters/ws.d.ts +1 -2
- package/dist/adapters/ws.d.ts.map +1 -1
- package/dist/adapters/ws.js +98 -81
- package/dist/adapters/ws.mjs +98 -81
- package/dist/bundle-analysis.json +196 -137
- package/dist/index.js +5 -3
- package/dist/index.mjs +2 -1
- package/dist/observable/observable.d.ts +1 -0
- package/dist/observable/observable.d.ts.map +1 -1
- package/dist/observable/observable.js +55 -0
- package/dist/observable/observable.mjs +55 -1
- package/dist/unstable-core-do-not-import/createProxy.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/contentType.d.ts +7 -4
- package/dist/unstable-core-do-not-import/http/contentType.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/contentType.js +55 -17
- package/dist/unstable-core-do-not-import/http/contentType.mjs +56 -18
- package/dist/unstable-core-do-not-import/http/resolveResponse.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/resolveResponse.js +302 -149
- package/dist/unstable-core-do-not-import/http/resolveResponse.mjs +301 -148
- package/dist/unstable-core-do-not-import/http/types.d.ts +34 -5
- package/dist/unstable-core-do-not-import/http/types.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/initTRPC.d.ts +12 -12
- package/dist/unstable-core-do-not-import/initTRPC.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/middleware.d.ts +3 -3
- package/dist/unstable-core-do-not-import/middleware.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +3 -1
- package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/rootConfig.d.ts +12 -0
- package/dist/unstable-core-do-not-import/rootConfig.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/router.d.ts +2 -2
- package/dist/unstable-core-do-not-import/router.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/router.js +6 -0
- package/dist/unstable-core-do-not-import/router.mjs +6 -0
- package/dist/unstable-core-do-not-import/stream/{stream.d.ts → jsonl.d.ts} +5 -5
- package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/{stream.js → jsonl.js} +90 -89
- package/dist/unstable-core-do-not-import/stream/{stream.mjs → jsonl.mjs} +89 -88
- package/dist/unstable-core-do-not-import/stream/sse.d.ts +95 -0
- package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/sse.js +175 -0
- package/dist/unstable-core-do-not-import/stream/sse.mjs +169 -0
- package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts +18 -0
- package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/createDeferred.js +46 -0
- package/dist/unstable-core-do-not-import/stream/utils/createDeferred.mjs +43 -0
- package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts +10 -0
- package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.js +31 -0
- package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.mjs +29 -0
- package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts +7 -0
- package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/transformer.d.ts +5 -5
- package/dist/unstable-core-do-not-import/utils.d.ts +4 -0
- package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/utils.js +4 -0
- package/dist/unstable-core-do-not-import/utils.mjs +4 -1
- package/dist/unstable-core-do-not-import.d.ts +2 -1
- package/dist/unstable-core-do-not-import.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import.js +11 -4
- package/dist/unstable-core-do-not-import.mjs +3 -2
- package/package.json +3 -3
- package/src/@trpc/server/index.ts +1 -0
- package/src/adapters/node-http/incomingMessageToRequest.ts +3 -2
- package/src/adapters/node-http/nodeHTTPRequestHandler.ts +32 -7
- package/src/adapters/ws.ts +101 -75
- package/src/observable/observable.ts +63 -0
- package/src/unstable-core-do-not-import/http/contentType.ts +78 -21
- package/src/unstable-core-do-not-import/http/resolveResponse.ts +331 -164
- package/src/unstable-core-do-not-import/http/types.ts +42 -5
- package/src/unstable-core-do-not-import/procedureBuilder.ts +8 -1
- package/src/unstable-core-do-not-import/rootConfig.ts +12 -0
- package/src/unstable-core-do-not-import/router.ts +12 -0
- package/src/unstable-core-do-not-import/stream/{stream.ts → jsonl.ts} +99 -85
- package/src/unstable-core-do-not-import/stream/sse.ts +291 -0
- package/src/unstable-core-do-not-import/stream/utils/createDeferred.ts +48 -0
- package/src/unstable-core-do-not-import/stream/utils/createReadableStream.ts +31 -0
- package/src/unstable-core-do-not-import/stream/utils/createServer.ts +46 -0
- package/src/unstable-core-do-not-import/utils.ts +5 -0
- package/src/unstable-core-do-not-import.ts +2 -1
- package/dist/unstable-core-do-not-import/stream/stream.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/unstable-core-do-not-import/utils.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,eAAO,MAAM,WAAW,eAAwB,CAAC;AACjD,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC;AAE7C;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzE,IAAI,EAAE,KAAK,EACX,GAAG,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,GACxB,KAAK,CAYP;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,KAAK,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC;AACxE,wBAAgB,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,KAAK,CAEnD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,GAAG,EAAE,IAAI,GACR,IAAI,CAEN;AAKD,wBAAgB,eAAe,CAAC,MAAM,EACpC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,aAAa,CAAC,MAAM,CAAC,CAIhC"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/unstable-core-do-not-import/utils.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,eAAO,MAAM,WAAW,eAAwB,CAAC;AACjD,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC;AAE7C;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzE,IAAI,EAAE,KAAK,EACX,GAAG,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,GACxB,KAAK,CAYP;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,KAAK,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC;AACxE,wBAAgB,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,KAAK,CAEnD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,GAAG,EAAE,IAAI,GACR,IAAI,CAEN;AAKD,wBAAgB,eAAe,CAAC,MAAM,EACpC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,aAAa,CAAC,MAAM,CAAC,CAIhC;AAED;;GAEG;AACH,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,MAAM,MAAM,KAAG,MAAc,CAAC"}
|
|
@@ -35,10 +35,14 @@ const asyncIteratorsSupported = typeof Symbol === 'function' && !!Symbol.asyncIt
|
|
|
35
35
|
function isAsyncIterable(value) {
|
|
36
36
|
return asyncIteratorsSupported && isObject(value) && Symbol.asyncIterator in value;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Run an IIFE
|
|
40
|
+
*/ const run = (fn)=>fn();
|
|
38
41
|
|
|
39
42
|
exports.isAsyncIterable = isAsyncIterable;
|
|
40
43
|
exports.isFunction = isFunction;
|
|
41
44
|
exports.isObject = isObject;
|
|
42
45
|
exports.mergeWithoutOverrides = mergeWithoutOverrides;
|
|
43
46
|
exports.omitPrototype = omitPrototype;
|
|
47
|
+
exports.run = run;
|
|
44
48
|
exports.unsetMarker = unsetMarker;
|
|
@@ -33,5 +33,8 @@ const asyncIteratorsSupported = typeof Symbol === 'function' && !!Symbol.asyncIt
|
|
|
33
33
|
function isAsyncIterable(value) {
|
|
34
34
|
return asyncIteratorsSupported && isObject(value) && Symbol.asyncIterator in value;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Run an IIFE
|
|
38
|
+
*/ const run = (fn)=>fn();
|
|
36
39
|
|
|
37
|
-
export { isAsyncIterable, isFunction, isObject, mergeWithoutOverrides, omitPrototype, unsetMarker };
|
|
40
|
+
export { isAsyncIterable, isFunction, isObject, mergeWithoutOverrides, omitPrototype, run, unsetMarker };
|
|
@@ -33,5 +33,6 @@ export * from './unstable-core-do-not-import/rpc';
|
|
|
33
33
|
export * from './unstable-core-do-not-import/transformer';
|
|
34
34
|
export * from './unstable-core-do-not-import/types';
|
|
35
35
|
export * from './unstable-core-do-not-import/utils';
|
|
36
|
-
export * from './unstable-core-do-not-import/stream/
|
|
36
|
+
export * from './unstable-core-do-not-import/stream/jsonl';
|
|
37
|
+
export * from './unstable-core-do-not-import/stream/sse';
|
|
37
38
|
//# sourceMappingURL=unstable-core-do-not-import.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unstable-core-do-not-import.d.ts","sourceRoot":"","sources":["../src/unstable-core-do-not-import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,mDAAmD,CAAC;AAClE,cAAc,oDAAoD,CAAC;AACnE,cAAc,mDAAmD,CAAC;AAClE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mDAAmD,CAAC;AAClE,cAAc,yDAAyD,CAAC;AACxE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uDAAuD,CAAC;AACtE,cAAc,sDAAsD,CAAC;AACrE,cAAc,oDAAoD,CAAC;AACnE,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,wCAAwC,CAAC;AACvD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,
|
|
1
|
+
{"version":3,"file":"unstable-core-do-not-import.d.ts","sourceRoot":"","sources":["../src/unstable-core-do-not-import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,mDAAmD,CAAC;AAClE,cAAc,oDAAoD,CAAC;AACnE,cAAc,mDAAmD,CAAC;AAClE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mDAAmD,CAAC;AAClE,cAAc,yDAAyD,CAAC;AACxE,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uDAAuD,CAAC;AACtE,cAAc,sDAAsD,CAAC;AACrE,cAAc,oDAAoD,CAAC;AACnE,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,wCAAwC,CAAC;AACvD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,0CAA0C,CAAC"}
|
|
@@ -22,7 +22,8 @@ var parseTRPCMessage = require('./unstable-core-do-not-import/rpc/parseTRPCMessa
|
|
|
22
22
|
var transformer = require('./unstable-core-do-not-import/transformer.js');
|
|
23
23
|
var types = require('./unstable-core-do-not-import/types.js');
|
|
24
24
|
var utils = require('./unstable-core-do-not-import/utils.js');
|
|
25
|
-
var
|
|
25
|
+
var jsonl = require('./unstable-core-do-not-import/stream/jsonl.js');
|
|
26
|
+
var sse = require('./unstable-core-do-not-import/stream/sse.js');
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
|
|
@@ -67,7 +68,13 @@ exports.isFunction = utils.isFunction;
|
|
|
67
68
|
exports.isObject = utils.isObject;
|
|
68
69
|
exports.mergeWithoutOverrides = utils.mergeWithoutOverrides;
|
|
69
70
|
exports.omitPrototype = utils.omitPrototype;
|
|
71
|
+
exports.run = utils.run;
|
|
70
72
|
exports.unsetMarker = utils.unsetMarker;
|
|
71
|
-
exports.isPromise =
|
|
72
|
-
exports.jsonlStreamConsumer =
|
|
73
|
-
exports.jsonlStreamProducer =
|
|
73
|
+
exports.isPromise = jsonl.isPromise;
|
|
74
|
+
exports.jsonlStreamConsumer = jsonl.jsonlStreamConsumer;
|
|
75
|
+
exports.jsonlStreamProducer = jsonl.jsonlStreamProducer;
|
|
76
|
+
exports.isServerSentEventEnvelope = sse.isServerSentEventEnvelope;
|
|
77
|
+
exports.sse = sse.sse;
|
|
78
|
+
exports.sseHeaders = sse.sseHeaders;
|
|
79
|
+
exports.sseStreamConsumer = sse.sseStreamConsumer;
|
|
80
|
+
exports.sseStreamProducer = sse.sseStreamProducer;
|
|
@@ -19,5 +19,6 @@ export { TRPC_ERROR_CODES_BY_KEY, TRPC_ERROR_CODES_BY_NUMBER } from './unstable-
|
|
|
19
19
|
export { parseTRPCMessage } from './unstable-core-do-not-import/rpc/parseTRPCMessage.mjs';
|
|
20
20
|
export { defaultTransformer, getDataTransformer, transformResult, transformTRPCResponse } from './unstable-core-do-not-import/transformer.mjs';
|
|
21
21
|
export { ERROR_SYMBOL } from './unstable-core-do-not-import/types.mjs';
|
|
22
|
-
export { isAsyncIterable, isFunction, isObject, mergeWithoutOverrides, omitPrototype, unsetMarker } from './unstable-core-do-not-import/utils.mjs';
|
|
23
|
-
export { isPromise, jsonlStreamConsumer, jsonlStreamProducer } from './unstable-core-do-not-import/stream/
|
|
22
|
+
export { isAsyncIterable, isFunction, isObject, mergeWithoutOverrides, omitPrototype, run, unsetMarker } from './unstable-core-do-not-import/utils.mjs';
|
|
23
|
+
export { isPromise, jsonlStreamConsumer, jsonlStreamProducer } from './unstable-core-do-not-import/stream/jsonl.mjs';
|
|
24
|
+
export { isServerSentEventEnvelope, sse, sseHeaders, sseStreamConsumer, sseStreamProducer } from './unstable-core-do-not-import/stream/sse.mjs';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trpc/server",
|
|
3
|
-
"version": "11.0.0-rc.
|
|
3
|
+
"version": "11.0.0-rc.419+343b6de2e",
|
|
4
4
|
"description": "The tRPC server library",
|
|
5
5
|
"author": "KATT",
|
|
6
6
|
"license": "MIT",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"superstruct": "^1.0.0",
|
|
141
141
|
"tslib": "^2.5.0",
|
|
142
142
|
"tsx": "^4.0.0",
|
|
143
|
-
"typescript": "^5.
|
|
143
|
+
"typescript": "^5.5.0",
|
|
144
144
|
"valibot": "^0.33.0",
|
|
145
145
|
"ws": "^8.0.0",
|
|
146
146
|
"yup": "^1.0.0",
|
|
@@ -149,5 +149,5 @@
|
|
|
149
149
|
"funding": [
|
|
150
150
|
"https://trpc.io/sponsor"
|
|
151
151
|
],
|
|
152
|
-
"gitHead": "
|
|
152
|
+
"gitHead": "343b6de2ea719347bffe8332f37589c66c323349"
|
|
153
153
|
}
|
|
@@ -68,8 +68,9 @@ export function incomingMessageToRequest(
|
|
|
68
68
|
const ac = new AbortController();
|
|
69
69
|
const headers = new Headers(req.headers as any);
|
|
70
70
|
const url = `http://${headers.get('host')}${req.url}`;
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
req.once('aborted', () => {
|
|
72
|
+
ac.abort();
|
|
73
|
+
});
|
|
73
74
|
|
|
74
75
|
const init: RequestInit = {
|
|
75
76
|
headers,
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
// @trpc/server
|
|
12
12
|
|
|
13
|
-
import { Readable } from 'node:stream';
|
|
14
13
|
import { getTRPCErrorFromUnknown, type AnyRouter } from '../../@trpc/server';
|
|
15
14
|
import type { ResolveHTTPRequestOptionsContextFn } from '../../@trpc/server/http';
|
|
16
15
|
import { resolveResponse } from '../../@trpc/server/http';
|
|
@@ -56,17 +55,43 @@ export async function nodeHTTPRequestHandler<
|
|
|
56
55
|
},
|
|
57
56
|
});
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
const { res } = opts;
|
|
59
|
+
if (res.statusCode === 200) {
|
|
60
60
|
// if the status code is set, we assume that it's been manually overridden
|
|
61
|
-
|
|
61
|
+
res.statusCode = response.status;
|
|
62
62
|
}
|
|
63
63
|
for (const [key, value] of response.headers) {
|
|
64
|
-
|
|
64
|
+
res.setHeader(key, value);
|
|
65
65
|
}
|
|
66
66
|
if (response.body) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
const reader = response.body.getReader();
|
|
68
|
+
const onAbort = () => {
|
|
69
|
+
// cancelling the reader will cause the whole stream to be cancelled
|
|
70
|
+
reader.cancel().catch(() => {
|
|
71
|
+
// console.error('reader.cancel() error', err);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
req.signal.addEventListener('abort', onAbort);
|
|
75
|
+
|
|
76
|
+
while (true) {
|
|
77
|
+
const { done, value } = await reader.read();
|
|
78
|
+
|
|
79
|
+
if (done) {
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
if (!res.writable) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
if (!res.write(value)) {
|
|
86
|
+
await new Promise<void>((resolve) => {
|
|
87
|
+
res.once('drain', resolve);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// IMPORTANT - flush the response buffer, otherwise the client will not receive the data until `.end()`
|
|
91
|
+
res.flush?.();
|
|
92
|
+
}
|
|
93
|
+
req.signal.removeEventListener('abort', onAbort);
|
|
70
94
|
}
|
|
95
|
+
res.end();
|
|
71
96
|
});
|
|
72
97
|
}
|
package/src/adapters/ws.ts
CHANGED
|
@@ -16,15 +16,18 @@ import type { BaseHandlerOptions } from '../@trpc/server/http';
|
|
|
16
16
|
import { parseTRPCMessage } from '../@trpc/server/rpc';
|
|
17
17
|
// @trpc/server/rpc
|
|
18
18
|
import type {
|
|
19
|
-
JSONRPC2,
|
|
20
19
|
TRPCClientOutgoingMessage,
|
|
21
20
|
TRPCReconnectNotification,
|
|
22
21
|
TRPCResponseMessage,
|
|
23
22
|
} from '../@trpc/server/rpc';
|
|
24
23
|
import { isObservable } from '../observable';
|
|
25
|
-
import
|
|
24
|
+
import { observableToAsyncIterable } from '../observable/observable';
|
|
26
25
|
// eslint-disable-next-line no-restricted-imports
|
|
27
|
-
import
|
|
26
|
+
import {
|
|
27
|
+
isAsyncIterable,
|
|
28
|
+
run,
|
|
29
|
+
type MaybePromise,
|
|
30
|
+
} from '../unstable-core-do-not-import';
|
|
28
31
|
import type { NodeHTTPCreateContextFnOptions } from './node-http';
|
|
29
32
|
|
|
30
33
|
/**
|
|
@@ -88,7 +91,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
|
|
|
88
91
|
const { transformer } = router._def._config;
|
|
89
92
|
|
|
90
93
|
return async (client: ws.WebSocket, req: IncomingMessage) => {
|
|
91
|
-
const clientSubscriptions = new Map<number | string,
|
|
94
|
+
const clientSubscriptions = new Map<number | string, AbortController>();
|
|
92
95
|
|
|
93
96
|
function respond(untransformedJSON: TRPCResponseMessage) {
|
|
94
97
|
client.send(
|
|
@@ -98,21 +101,6 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
|
|
|
98
101
|
);
|
|
99
102
|
}
|
|
100
103
|
|
|
101
|
-
function stopSubscription(
|
|
102
|
-
subscription: Unsubscribable,
|
|
103
|
-
{ id, jsonrpc }: JSONRPC2.BaseEnvelope & { id: JSONRPC2.RequestId },
|
|
104
|
-
) {
|
|
105
|
-
subscription.unsubscribe();
|
|
106
|
-
|
|
107
|
-
respond({
|
|
108
|
-
id,
|
|
109
|
-
jsonrpc,
|
|
110
|
-
result: {
|
|
111
|
-
type: 'stopped',
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
104
|
const ctxPromise = createContext?.({ req, res: client });
|
|
117
105
|
let ctx: inferRouterContext<TRouter> | undefined = undefined;
|
|
118
106
|
|
|
@@ -126,11 +114,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
|
|
|
126
114
|
});
|
|
127
115
|
}
|
|
128
116
|
if (msg.method === 'subscription.stop') {
|
|
129
|
-
|
|
130
|
-
if (sub) {
|
|
131
|
-
stopSubscription(sub, { id, jsonrpc });
|
|
132
|
-
}
|
|
133
|
-
clientSubscriptions.delete(id);
|
|
117
|
+
clientSubscriptions.get(id)?.abort();
|
|
134
118
|
return;
|
|
135
119
|
}
|
|
136
120
|
const { path, input } = msg.params;
|
|
@@ -146,14 +130,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
|
|
|
146
130
|
type,
|
|
147
131
|
});
|
|
148
132
|
|
|
149
|
-
if (type
|
|
150
|
-
if (!isObservable(result)) {
|
|
151
|
-
throw new TRPCError({
|
|
152
|
-
message: `Subscription ${path} did not return an observable`,
|
|
153
|
-
code: 'INTERNAL_SERVER_ERROR',
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
} else {
|
|
133
|
+
if (type !== 'subscription') {
|
|
157
134
|
// send the value as data if the method is not a subscription
|
|
158
135
|
respond({
|
|
159
136
|
id,
|
|
@@ -166,62 +143,112 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
|
|
|
166
143
|
return;
|
|
167
144
|
}
|
|
168
145
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
type: 'data',
|
|
177
|
-
data,
|
|
178
|
-
},
|
|
179
|
-
});
|
|
180
|
-
},
|
|
181
|
-
error(err) {
|
|
182
|
-
const error = getTRPCErrorFromUnknown(err);
|
|
183
|
-
opts.onError?.({ error, path, type, ctx, req, input });
|
|
184
|
-
respond({
|
|
185
|
-
id,
|
|
186
|
-
jsonrpc,
|
|
187
|
-
error: getErrorShape({
|
|
188
|
-
config: router._def._config,
|
|
189
|
-
error,
|
|
190
|
-
type,
|
|
191
|
-
path,
|
|
192
|
-
input,
|
|
193
|
-
ctx,
|
|
194
|
-
}),
|
|
195
|
-
});
|
|
196
|
-
},
|
|
197
|
-
complete() {
|
|
198
|
-
respond({
|
|
199
|
-
id,
|
|
200
|
-
jsonrpc,
|
|
201
|
-
result: {
|
|
202
|
-
type: 'stopped',
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
|
-
},
|
|
206
|
-
});
|
|
146
|
+
if (!isObservable(result) && !isAsyncIterable(result)) {
|
|
147
|
+
throw new TRPCError({
|
|
148
|
+
message: `Subscription ${path} did not return an observable or a AsyncGenerator`,
|
|
149
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
207
153
|
/* istanbul ignore next -- @preserve */
|
|
208
154
|
if (client.readyState !== WEBSOCKET_OPEN) {
|
|
209
155
|
// if the client got disconnected whilst initializing the subscription
|
|
210
156
|
// no need to send stopped message if the client is disconnected
|
|
211
|
-
|
|
157
|
+
|
|
212
158
|
return;
|
|
213
159
|
}
|
|
214
160
|
|
|
215
161
|
/* istanbul ignore next -- @preserve */
|
|
216
162
|
if (clientSubscriptions.has(id)) {
|
|
217
163
|
// duplicate request ids for client
|
|
218
|
-
|
|
164
|
+
|
|
219
165
|
throw new TRPCError({
|
|
220
166
|
message: `Duplicate id ${id}`,
|
|
221
167
|
code: 'BAD_REQUEST',
|
|
222
168
|
});
|
|
223
169
|
}
|
|
224
|
-
|
|
170
|
+
|
|
171
|
+
const iterable = isObservable(result)
|
|
172
|
+
? observableToAsyncIterable(result)
|
|
173
|
+
: result;
|
|
174
|
+
|
|
175
|
+
const iterator: AsyncIterator<unknown> =
|
|
176
|
+
iterable[Symbol.asyncIterator]();
|
|
177
|
+
const abortController = new AbortController();
|
|
178
|
+
|
|
179
|
+
const abortPromise = new Promise<'abort'>((resolve) => {
|
|
180
|
+
abortController.signal.onabort = () => resolve('abort');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
run(async () => {
|
|
184
|
+
while (true) {
|
|
185
|
+
const next = await Promise.race([
|
|
186
|
+
iterator.next().catch(getTRPCErrorFromUnknown),
|
|
187
|
+
abortPromise,
|
|
188
|
+
]);
|
|
189
|
+
|
|
190
|
+
if (next === 'abort') {
|
|
191
|
+
await iterator.return?.();
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
if (next instanceof Error) {
|
|
195
|
+
const error = getTRPCErrorFromUnknown(next);
|
|
196
|
+
opts.onError?.({ error, path, type, ctx, req, input });
|
|
197
|
+
respond({
|
|
198
|
+
id,
|
|
199
|
+
jsonrpc,
|
|
200
|
+
error: getErrorShape({
|
|
201
|
+
config: router._def._config,
|
|
202
|
+
error,
|
|
203
|
+
type,
|
|
204
|
+
path,
|
|
205
|
+
input,
|
|
206
|
+
ctx,
|
|
207
|
+
}),
|
|
208
|
+
});
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
if (next.done) {
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
respond({
|
|
216
|
+
id,
|
|
217
|
+
jsonrpc,
|
|
218
|
+
result: {
|
|
219
|
+
type: 'data',
|
|
220
|
+
data: next.value,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
await iterator.return?.();
|
|
226
|
+
respond({
|
|
227
|
+
id,
|
|
228
|
+
jsonrpc,
|
|
229
|
+
result: {
|
|
230
|
+
type: 'stopped',
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
clientSubscriptions.delete(id);
|
|
234
|
+
}).catch((cause) => {
|
|
235
|
+
const error = getTRPCErrorFromUnknown(cause);
|
|
236
|
+
opts.onError?.({ error, path, type, ctx, req, input });
|
|
237
|
+
respond({
|
|
238
|
+
id,
|
|
239
|
+
jsonrpc,
|
|
240
|
+
error: getErrorShape({
|
|
241
|
+
config: router._def._config,
|
|
242
|
+
error,
|
|
243
|
+
type,
|
|
244
|
+
path,
|
|
245
|
+
input,
|
|
246
|
+
ctx,
|
|
247
|
+
}),
|
|
248
|
+
});
|
|
249
|
+
abortController.abort();
|
|
250
|
+
});
|
|
251
|
+
clientSubscriptions.set(id, abortController);
|
|
225
252
|
|
|
226
253
|
respond({
|
|
227
254
|
id,
|
|
@@ -250,7 +277,6 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
|
|
|
250
277
|
}
|
|
251
278
|
client.on('message', async (message) => {
|
|
252
279
|
try {
|
|
253
|
-
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
254
280
|
const msgJSON: unknown = JSON.parse(message.toString());
|
|
255
281
|
const msgs: unknown[] = Array.isArray(msgJSON) ? msgJSON : [msgJSON];
|
|
256
282
|
const promises = msgs
|
|
@@ -294,7 +320,7 @@ export function getWSConnectionHandler<TRouter extends AnyRouter>(
|
|
|
294
320
|
|
|
295
321
|
client.once('close', () => {
|
|
296
322
|
for (const sub of clientSubscriptions.values()) {
|
|
297
|
-
sub.
|
|
323
|
+
sub.abort();
|
|
298
324
|
}
|
|
299
325
|
clientSubscriptions.clear();
|
|
300
326
|
});
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
OperatorFunction,
|
|
5
5
|
TeardownLogic,
|
|
6
6
|
UnaryFunction,
|
|
7
|
+
Unsubscribable,
|
|
7
8
|
} from './types';
|
|
8
9
|
|
|
9
10
|
/** @public */
|
|
@@ -136,3 +137,65 @@ export function observableToPromise<TValue>(
|
|
|
136
137
|
abort: abort!,
|
|
137
138
|
};
|
|
138
139
|
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @internal
|
|
143
|
+
*/
|
|
144
|
+
function observableToReadableStream<TValue>(
|
|
145
|
+
observable: Observable<TValue, unknown>,
|
|
146
|
+
): ReadableStream<TValue> {
|
|
147
|
+
let unsub: Unsubscribable | null = null;
|
|
148
|
+
return new ReadableStream<TValue>({
|
|
149
|
+
start(controller) {
|
|
150
|
+
unsub = observable.subscribe({
|
|
151
|
+
next(data) {
|
|
152
|
+
controller.enqueue(data);
|
|
153
|
+
},
|
|
154
|
+
error(err) {
|
|
155
|
+
controller.error(err);
|
|
156
|
+
},
|
|
157
|
+
complete() {
|
|
158
|
+
controller.close();
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
},
|
|
162
|
+
cancel() {
|
|
163
|
+
unsub?.unsubscribe();
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function observableToAsyncIterable<TValue>(
|
|
169
|
+
observable: Observable<TValue, unknown>,
|
|
170
|
+
): AsyncIterable<TValue> {
|
|
171
|
+
const stream = observableToReadableStream(observable);
|
|
172
|
+
|
|
173
|
+
const reader = stream.getReader();
|
|
174
|
+
const iterator: AsyncIterator<TValue> = {
|
|
175
|
+
async next() {
|
|
176
|
+
const value = await reader.read();
|
|
177
|
+
if (value.done) {
|
|
178
|
+
return {
|
|
179
|
+
value: undefined,
|
|
180
|
+
done: true,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
value: value.value,
|
|
185
|
+
done: false,
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
async return() {
|
|
189
|
+
await reader.cancel();
|
|
190
|
+
return {
|
|
191
|
+
value: undefined,
|
|
192
|
+
done: true,
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
[Symbol.asyncIterator]() {
|
|
198
|
+
return iterator;
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import { TRPCError } from '../error/TRPCError';
|
|
2
|
-
import type {
|
|
2
|
+
import type { AnyProcedure, ProcedureType } from '../procedure';
|
|
3
|
+
import type { AnyRouter } from '../router';
|
|
3
4
|
import { isObject, unsetMarker } from '../utils';
|
|
4
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
TRPCAcceptHeader,
|
|
7
|
+
TRPCRequestInfo,
|
|
8
|
+
TRPCRequestInfoBase,
|
|
9
|
+
} from './types';
|
|
10
|
+
|
|
11
|
+
type GetRequestInfoOptions = {
|
|
12
|
+
path: string;
|
|
13
|
+
req: Request;
|
|
14
|
+
searchParams: URLSearchParams;
|
|
15
|
+
headers: Headers;
|
|
16
|
+
router: AnyRouter;
|
|
17
|
+
};
|
|
5
18
|
|
|
6
19
|
type ContentTypeHandler = {
|
|
7
20
|
isMatch: (opts: Request) => boolean;
|
|
8
|
-
parse: (opts:
|
|
9
|
-
path: string;
|
|
10
|
-
req: Request;
|
|
11
|
-
searchParams: URLSearchParams;
|
|
12
|
-
config: RootConfig<any>;
|
|
13
|
-
}) => TRPCRequestInfo;
|
|
21
|
+
parse: (opts: GetRequestInfoOptions) => TRPCRequestInfo;
|
|
14
22
|
};
|
|
15
23
|
|
|
16
24
|
/**
|
|
@@ -82,7 +90,7 @@ const jsonContentTypeHandler: ContentTypeHandler = {
|
|
|
82
90
|
|
|
83
91
|
if (!isBatchCall) {
|
|
84
92
|
return {
|
|
85
|
-
0: opts.
|
|
93
|
+
0: opts.router._def._config.transformer.input.deserialize(inputs),
|
|
86
94
|
};
|
|
87
95
|
}
|
|
88
96
|
|
|
@@ -96,26 +104,74 @@ const jsonContentTypeHandler: ContentTypeHandler = {
|
|
|
96
104
|
for (const index of paths.keys()) {
|
|
97
105
|
const input = inputs[index];
|
|
98
106
|
if (input !== undefined) {
|
|
99
|
-
acc[index] =
|
|
107
|
+
acc[index] =
|
|
108
|
+
opts.router._def._config.transformer.input.deserialize(input);
|
|
100
109
|
}
|
|
101
110
|
}
|
|
102
111
|
|
|
103
112
|
return acc;
|
|
104
113
|
});
|
|
105
114
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
115
|
+
const calls = paths.map((path, index): TRPCRequestInfo['calls'][number] => {
|
|
116
|
+
const procedure: AnyProcedure | null =
|
|
117
|
+
opts.router._def.procedures[path] ?? null;
|
|
118
|
+
return {
|
|
109
119
|
path,
|
|
120
|
+
procedure,
|
|
110
121
|
getRawInput: async () => {
|
|
111
122
|
const inputs = await getInputs.read();
|
|
112
|
-
|
|
123
|
+
let input = inputs[index];
|
|
124
|
+
|
|
125
|
+
if (procedure?._def.type === 'subscription') {
|
|
126
|
+
const lastEventId =
|
|
127
|
+
opts.headers.get('last-event-id') ??
|
|
128
|
+
opts.searchParams.get('lastEventId') ??
|
|
129
|
+
opts.searchParams.get('Last-Event-Id');
|
|
130
|
+
|
|
131
|
+
if (lastEventId) {
|
|
132
|
+
if (isObject(input)) {
|
|
133
|
+
input = {
|
|
134
|
+
...input,
|
|
135
|
+
lastEventId: lastEventId,
|
|
136
|
+
};
|
|
137
|
+
} else {
|
|
138
|
+
input ??= {
|
|
139
|
+
lastEventId: lastEventId,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return input;
|
|
113
145
|
},
|
|
114
146
|
result: () => {
|
|
115
147
|
return getInputs.result()?.[index];
|
|
116
148
|
},
|
|
117
|
-
}
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const types = new Set(
|
|
153
|
+
calls.map((call) => call.procedure?._def.type).filter(Boolean),
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
/* istanbul ignore if -- @preserve */
|
|
157
|
+
if (types.size > 1) {
|
|
158
|
+
throw new TRPCError({
|
|
159
|
+
code: 'BAD_REQUEST',
|
|
160
|
+
message: `Cannot mix procedure types in call: ${Array.from(types).join(
|
|
161
|
+
', ',
|
|
162
|
+
)}`,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
const type: ProcedureType | 'unknown' =
|
|
166
|
+
types.values().next().value ?? 'unknown';
|
|
167
|
+
|
|
168
|
+
const info: TRPCRequestInfoBase = {
|
|
169
|
+
isBatchCall,
|
|
170
|
+
accept: req.headers.get('trpc-accept') as TRPCAcceptHeader | null,
|
|
171
|
+
calls,
|
|
172
|
+
type,
|
|
118
173
|
};
|
|
174
|
+
return info as TRPCRequestInfo;
|
|
119
175
|
},
|
|
120
176
|
};
|
|
121
177
|
|
|
@@ -137,14 +193,17 @@ const formDataContentTypeHandler: ContentTypeHandler = {
|
|
|
137
193
|
return fd;
|
|
138
194
|
});
|
|
139
195
|
return {
|
|
196
|
+
accept: null,
|
|
140
197
|
calls: [
|
|
141
198
|
{
|
|
142
199
|
path: opts.path,
|
|
143
200
|
getRawInput: getInputs.read,
|
|
144
201
|
result: getInputs.result,
|
|
202
|
+
procedure: opts.router._def.procedures[opts.path] ?? null,
|
|
145
203
|
},
|
|
146
204
|
],
|
|
147
205
|
isBatchCall: false,
|
|
206
|
+
type: 'mutation',
|
|
148
207
|
};
|
|
149
208
|
},
|
|
150
209
|
};
|
|
@@ -173,9 +232,12 @@ const octetStreamContentTypeHandler: ContentTypeHandler = {
|
|
|
173
232
|
path: opts.path,
|
|
174
233
|
getRawInput: getInputs.read,
|
|
175
234
|
result: getInputs.result,
|
|
235
|
+
procedure: opts.router._def.procedures[opts.path] ?? null,
|
|
176
236
|
},
|
|
177
237
|
],
|
|
178
238
|
isBatchCall: false,
|
|
239
|
+
accept: null,
|
|
240
|
+
type: 'mutation',
|
|
179
241
|
};
|
|
180
242
|
},
|
|
181
243
|
};
|
|
@@ -205,12 +267,7 @@ function getContentTypeHandler(req: Request): ContentTypeHandler {
|
|
|
205
267
|
});
|
|
206
268
|
}
|
|
207
269
|
|
|
208
|
-
export function getRequestInfo(opts: {
|
|
209
|
-
path: string;
|
|
210
|
-
req: Request;
|
|
211
|
-
searchParams: URLSearchParams;
|
|
212
|
-
config: RootConfig<any>;
|
|
213
|
-
}): TRPCRequestInfo {
|
|
270
|
+
export function getRequestInfo(opts: GetRequestInfoOptions): TRPCRequestInfo {
|
|
214
271
|
const handler = getContentTypeHandler(opts.req);
|
|
215
272
|
return handler.parse(opts);
|
|
216
273
|
}
|