@trpc/server 11.0.0-rc.417 → 11.0.0-rc.421
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 +183 -124
- 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 +86 -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 +178 -0
- package/dist/unstable-core-do-not-import/stream/sse.mjs +172 -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 +288 -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,20 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var TRPCError = require('../error/TRPCError.js');
|
|
3
4
|
var utils = require('../utils.js');
|
|
5
|
+
var createDeferred = require('./utils/createDeferred.js');
|
|
6
|
+
var createReadableStream = require('./utils/createReadableStream.js');
|
|
4
7
|
|
|
5
|
-
// ---------- utils
|
|
6
|
-
function createReadableStream() {
|
|
7
|
-
let controller = null;
|
|
8
|
-
const stream = new ReadableStream({
|
|
9
|
-
start (c) {
|
|
10
|
-
controller = c;
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
return [
|
|
14
|
-
stream,
|
|
15
|
-
controller
|
|
16
|
-
];
|
|
17
|
-
}
|
|
18
8
|
// ---------- types
|
|
19
9
|
const CHUNK_VALUE_TYPE_PROMISE = 0;
|
|
20
10
|
const CHUNK_VALUE_TYPE_ASYNC_ITERABLE = 1;
|
|
@@ -36,14 +26,14 @@ function createBatchStreamProducer(opts) {
|
|
|
36
26
|
const { data } = opts;
|
|
37
27
|
let counter = 0;
|
|
38
28
|
const placeholder = 0;
|
|
39
|
-
const
|
|
29
|
+
const stream = createReadableStream.createReadableStream();
|
|
40
30
|
const pending = new Set();
|
|
41
31
|
function maybeClose() {
|
|
42
|
-
if (pending.size === 0) {
|
|
43
|
-
controller.close();
|
|
32
|
+
if (pending.size === 0 && !stream.cancelled()) {
|
|
33
|
+
stream.controller.close();
|
|
44
34
|
}
|
|
45
35
|
}
|
|
46
|
-
function
|
|
36
|
+
function dehydratePromise(promise, path) {
|
|
47
37
|
//
|
|
48
38
|
const error = checkMaxDepth(path);
|
|
49
39
|
if (error) {
|
|
@@ -54,25 +44,28 @@ function createBatchStreamProducer(opts) {
|
|
|
54
44
|
}
|
|
55
45
|
const idx = counter++;
|
|
56
46
|
pending.add(idx);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
47
|
+
Promise.race([
|
|
48
|
+
promise,
|
|
49
|
+
stream.cancelledPromise
|
|
50
|
+
]).then((it)=>{
|
|
51
|
+
if (it === null) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
stream.controller.enqueue([
|
|
62
55
|
idx,
|
|
63
56
|
PROMISE_STATUS_FULFILLED,
|
|
64
|
-
|
|
57
|
+
dehydrate(it, path)
|
|
65
58
|
]);
|
|
66
|
-
}).catch((
|
|
59
|
+
}).catch((cause)=>{
|
|
67
60
|
opts.onError?.({
|
|
68
|
-
error,
|
|
61
|
+
error: cause,
|
|
69
62
|
path
|
|
70
63
|
});
|
|
71
|
-
enqueue([
|
|
64
|
+
stream.controller.enqueue([
|
|
72
65
|
idx,
|
|
73
66
|
PROMISE_STATUS_REJECTED,
|
|
74
67
|
opts.formatError?.({
|
|
75
|
-
error,
|
|
68
|
+
error: cause,
|
|
76
69
|
path
|
|
77
70
|
})
|
|
78
71
|
]);
|
|
@@ -82,7 +75,7 @@ function createBatchStreamProducer(opts) {
|
|
|
82
75
|
});
|
|
83
76
|
return idx;
|
|
84
77
|
}
|
|
85
|
-
function
|
|
78
|
+
function dehydrateAsyncIterable(iterable, path) {
|
|
86
79
|
const error = checkMaxDepth(path);
|
|
87
80
|
if (error) {
|
|
88
81
|
iterable = {
|
|
@@ -93,37 +86,58 @@ function createBatchStreamProducer(opts) {
|
|
|
93
86
|
}
|
|
94
87
|
const idx = counter++;
|
|
95
88
|
pending.add(idx);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
89
|
+
utils.run(async ()=>{
|
|
90
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
91
|
+
while(true){
|
|
92
|
+
const next = await Promise.race([
|
|
93
|
+
iterator.next().catch(TRPCError.getTRPCErrorFromUnknown),
|
|
94
|
+
stream.cancelledPromise
|
|
95
|
+
]);
|
|
96
|
+
if (next instanceof Error) {
|
|
97
|
+
opts.onError?.({
|
|
98
|
+
error: next,
|
|
99
|
+
path
|
|
100
|
+
});
|
|
101
|
+
stream.controller.enqueue([
|
|
100
102
|
idx,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
ASYNC_ITERABLE_STATUS_ERROR,
|
|
104
|
+
opts.formatError?.({
|
|
105
|
+
error: next,
|
|
106
|
+
path
|
|
107
|
+
})
|
|
103
108
|
]);
|
|
109
|
+
return;
|
|
104
110
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
if (next === 'cancelled') {
|
|
112
|
+
await iterator.return?.();
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
if (next.done) {
|
|
116
|
+
stream.controller.enqueue([
|
|
117
|
+
idx,
|
|
118
|
+
ASYNC_ITERABLE_STATUS_DONE
|
|
119
|
+
]);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
stream.controller.enqueue([
|
|
115
123
|
idx,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
error,
|
|
119
|
-
path
|
|
120
|
-
})
|
|
124
|
+
ASYNC_ITERABLE_STATUS_VALUE,
|
|
125
|
+
dehydrate(next.value, path)
|
|
121
126
|
]);
|
|
122
|
-
} finally{
|
|
123
|
-
pending.delete(idx);
|
|
124
|
-
maybeClose();
|
|
125
127
|
}
|
|
126
|
-
|
|
128
|
+
pending.delete(idx);
|
|
129
|
+
maybeClose();
|
|
130
|
+
}).catch((cause)=>{
|
|
131
|
+
// this shouldn't happen, but node crashes if we don't catch it
|
|
132
|
+
opts.onError?.({
|
|
133
|
+
error: new Error('You found a bug - please report it on https://github.com/trpc/trpc', // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
134
|
+
// @ts-ignore https://github.com/tc39/proposal-error-cause
|
|
135
|
+
{
|
|
136
|
+
cause
|
|
137
|
+
}),
|
|
138
|
+
path
|
|
139
|
+
});
|
|
140
|
+
});
|
|
127
141
|
return idx;
|
|
128
142
|
}
|
|
129
143
|
function checkMaxDepth(path) {
|
|
@@ -132,11 +146,11 @@ function createBatchStreamProducer(opts) {
|
|
|
132
146
|
}
|
|
133
147
|
return null;
|
|
134
148
|
}
|
|
135
|
-
function
|
|
149
|
+
function dehydrateChunk(value, path) {
|
|
136
150
|
if (isPromise(value)) {
|
|
137
151
|
return [
|
|
138
152
|
CHUNK_VALUE_TYPE_PROMISE,
|
|
139
|
-
|
|
153
|
+
dehydratePromise(value, path)
|
|
140
154
|
];
|
|
141
155
|
}
|
|
142
156
|
if (utils.isAsyncIterable(value)) {
|
|
@@ -145,13 +159,13 @@ function createBatchStreamProducer(opts) {
|
|
|
145
159
|
}
|
|
146
160
|
return [
|
|
147
161
|
CHUNK_VALUE_TYPE_ASYNC_ITERABLE,
|
|
148
|
-
|
|
162
|
+
dehydrateAsyncIterable(value, path)
|
|
149
163
|
];
|
|
150
164
|
}
|
|
151
165
|
return null;
|
|
152
166
|
}
|
|
153
|
-
function
|
|
154
|
-
const reg =
|
|
167
|
+
function dehydrate(value, path) {
|
|
168
|
+
const reg = dehydrateChunk(value, path);
|
|
155
169
|
if (reg) {
|
|
156
170
|
return [
|
|
157
171
|
[
|
|
@@ -173,7 +187,7 @@ function createBatchStreamProducer(opts) {
|
|
|
173
187
|
const newObj = {};
|
|
174
188
|
const asyncValues = [];
|
|
175
189
|
for (const [key, item] of Object.entries(value)){
|
|
176
|
-
const transformed =
|
|
190
|
+
const transformed = dehydrateChunk(item, [
|
|
177
191
|
...path,
|
|
178
192
|
key
|
|
179
193
|
]);
|
|
@@ -196,13 +210,13 @@ function createBatchStreamProducer(opts) {
|
|
|
196
210
|
}
|
|
197
211
|
const newHead = {};
|
|
198
212
|
for (const [key, item] of Object.entries(data)){
|
|
199
|
-
newHead[key] =
|
|
213
|
+
newHead[key] = dehydrate(item, [
|
|
200
214
|
key
|
|
201
215
|
]);
|
|
202
216
|
}
|
|
203
217
|
return [
|
|
204
218
|
newHead,
|
|
205
|
-
stream
|
|
219
|
+
stream.readable
|
|
206
220
|
];
|
|
207
221
|
}
|
|
208
222
|
/**
|
|
@@ -246,7 +260,7 @@ class AsyncError extends Error {
|
|
|
246
260
|
const nodeJsStreamToReaderEsque = (source)=>{
|
|
247
261
|
return {
|
|
248
262
|
getReader () {
|
|
249
|
-
const
|
|
263
|
+
const { readable , controller } = createReadableStream.createReadableStream();
|
|
250
264
|
source.on('data', (chunk)=>{
|
|
251
265
|
controller.enqueue(chunk);
|
|
252
266
|
});
|
|
@@ -256,7 +270,7 @@ const nodeJsStreamToReaderEsque = (source)=>{
|
|
|
256
270
|
source.on('error', (error)=>{
|
|
257
271
|
controller.error(error);
|
|
258
272
|
});
|
|
259
|
-
return
|
|
273
|
+
return readable.getReader();
|
|
260
274
|
}
|
|
261
275
|
};
|
|
262
276
|
};
|
|
@@ -302,19 +316,6 @@ function createConsumerStream(from) {
|
|
|
302
316
|
}
|
|
303
317
|
}));
|
|
304
318
|
}
|
|
305
|
-
function createDeferred() {
|
|
306
|
-
let resolve;
|
|
307
|
-
let reject;
|
|
308
|
-
const promise = new Promise((res, rej)=>{
|
|
309
|
-
resolve = res;
|
|
310
|
-
reject = rej;
|
|
311
|
-
});
|
|
312
|
-
return {
|
|
313
|
-
promise,
|
|
314
|
-
resolve: resolve,
|
|
315
|
-
reject: reject
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
319
|
/**
|
|
319
320
|
* JSON Lines stream consumer
|
|
320
321
|
* @see https://jsonlines.org/
|
|
@@ -328,12 +329,12 @@ function createDeferred() {
|
|
|
328
329
|
}
|
|
329
330
|
}));
|
|
330
331
|
}
|
|
331
|
-
let headDeferred = createDeferred();
|
|
332
|
+
let headDeferred = createDeferred.createDeferred();
|
|
332
333
|
const chunkDeferred = new Map();
|
|
333
334
|
const controllers = new Map();
|
|
334
|
-
function
|
|
335
|
+
function hydrateChunkDefinition(value) {
|
|
335
336
|
const [_path, type, chunkId] = value;
|
|
336
|
-
const
|
|
337
|
+
const { readable , controller } = createReadableStream.createReadableStream();
|
|
337
338
|
controllers.set(chunkId, controller);
|
|
338
339
|
// resolve chunk deferred if it exists
|
|
339
340
|
const deferred = chunkDeferred.get(chunkId);
|
|
@@ -346,7 +347,7 @@ function createDeferred() {
|
|
|
346
347
|
{
|
|
347
348
|
return new Promise((resolve, reject)=>{
|
|
348
349
|
// listen for next value in the stream
|
|
349
|
-
const reader =
|
|
350
|
+
const reader = readable.getReader();
|
|
350
351
|
reader.read().then((it)=>{
|
|
351
352
|
if (it.done) {
|
|
352
353
|
reject(new Error('Promise chunk ended without value'));
|
|
@@ -360,7 +361,7 @@ function createDeferred() {
|
|
|
360
361
|
const [_chunkId, status, data] = value;
|
|
361
362
|
switch(status){
|
|
362
363
|
case PROMISE_STATUS_FULFILLED:
|
|
363
|
-
resolve(
|
|
364
|
+
resolve(hydrate(data));
|
|
364
365
|
break;
|
|
365
366
|
case PROMISE_STATUS_REJECTED:
|
|
366
367
|
reject(opts.formatError?.({
|
|
@@ -378,7 +379,7 @@ function createDeferred() {
|
|
|
378
379
|
{
|
|
379
380
|
return {
|
|
380
381
|
[Symbol.asyncIterator]: async function*() {
|
|
381
|
-
const reader =
|
|
382
|
+
const reader = readable.getReader();
|
|
382
383
|
while(true){
|
|
383
384
|
const { done , value } = await reader.read();
|
|
384
385
|
if (done) {
|
|
@@ -390,7 +391,7 @@ function createDeferred() {
|
|
|
390
391
|
const [_chunkId, status, data] = value;
|
|
391
392
|
switch(status){
|
|
392
393
|
case ASYNC_ITERABLE_STATUS_VALUE:
|
|
393
|
-
yield
|
|
394
|
+
yield hydrate(data);
|
|
394
395
|
break;
|
|
395
396
|
case ASYNC_ITERABLE_STATUS_DONE:
|
|
396
397
|
controllers.delete(chunkId);
|
|
@@ -407,15 +408,15 @@ function createDeferred() {
|
|
|
407
408
|
}
|
|
408
409
|
}
|
|
409
410
|
}
|
|
410
|
-
function
|
|
411
|
+
function hydrate(value) {
|
|
411
412
|
const [[data], ...asyncProps] = value;
|
|
412
413
|
for (const value1 of asyncProps){
|
|
413
|
-
const
|
|
414
|
+
const hydrated = hydrateChunkDefinition(value1);
|
|
414
415
|
const [path] = value1;
|
|
415
416
|
if (path === null) {
|
|
416
|
-
return
|
|
417
|
+
return hydrated;
|
|
417
418
|
}
|
|
418
|
-
data[path] =
|
|
419
|
+
data[path] = hydrated;
|
|
419
420
|
}
|
|
420
421
|
return data;
|
|
421
422
|
}
|
|
@@ -437,7 +438,7 @@ function createDeferred() {
|
|
|
437
438
|
if (headDeferred) {
|
|
438
439
|
const head = chunkOrHead;
|
|
439
440
|
for (const [key, value] of Object.entries(chunkOrHead)){
|
|
440
|
-
const parsed =
|
|
441
|
+
const parsed = hydrate(value);
|
|
441
442
|
head[key] = parsed;
|
|
442
443
|
}
|
|
443
444
|
headDeferred.resolve(head);
|
|
@@ -450,7 +451,7 @@ function createDeferred() {
|
|
|
450
451
|
if (!controller) {
|
|
451
452
|
let deferred = chunkDeferred.get(idx);
|
|
452
453
|
if (!deferred) {
|
|
453
|
-
deferred = createDeferred();
|
|
454
|
+
deferred = createDeferred.createDeferred();
|
|
454
455
|
chunkDeferred.set(idx, deferred);
|
|
455
456
|
}
|
|
456
457
|
controller = await deferred.promise;
|
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getTRPCErrorFromUnknown } from '../error/TRPCError.mjs';
|
|
2
|
+
import { isObject, isFunction, isAsyncIterable, run } from '../utils.mjs';
|
|
3
|
+
import { createDeferred } from './utils/createDeferred.mjs';
|
|
4
|
+
import { createReadableStream } from './utils/createReadableStream.mjs';
|
|
2
5
|
|
|
3
|
-
// ---------- utils
|
|
4
|
-
function createReadableStream() {
|
|
5
|
-
let controller = null;
|
|
6
|
-
const stream = new ReadableStream({
|
|
7
|
-
start (c) {
|
|
8
|
-
controller = c;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
return [
|
|
12
|
-
stream,
|
|
13
|
-
controller
|
|
14
|
-
];
|
|
15
|
-
}
|
|
16
6
|
// ---------- types
|
|
17
7
|
const CHUNK_VALUE_TYPE_PROMISE = 0;
|
|
18
8
|
const CHUNK_VALUE_TYPE_ASYNC_ITERABLE = 1;
|
|
@@ -34,14 +24,14 @@ function createBatchStreamProducer(opts) {
|
|
|
34
24
|
const { data } = opts;
|
|
35
25
|
let counter = 0;
|
|
36
26
|
const placeholder = 0;
|
|
37
|
-
const
|
|
27
|
+
const stream = createReadableStream();
|
|
38
28
|
const pending = new Set();
|
|
39
29
|
function maybeClose() {
|
|
40
|
-
if (pending.size === 0) {
|
|
41
|
-
controller.close();
|
|
30
|
+
if (pending.size === 0 && !stream.cancelled()) {
|
|
31
|
+
stream.controller.close();
|
|
42
32
|
}
|
|
43
33
|
}
|
|
44
|
-
function
|
|
34
|
+
function dehydratePromise(promise, path) {
|
|
45
35
|
//
|
|
46
36
|
const error = checkMaxDepth(path);
|
|
47
37
|
if (error) {
|
|
@@ -52,25 +42,28 @@ function createBatchStreamProducer(opts) {
|
|
|
52
42
|
}
|
|
53
43
|
const idx = counter++;
|
|
54
44
|
pending.add(idx);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
Promise.race([
|
|
46
|
+
promise,
|
|
47
|
+
stream.cancelledPromise
|
|
48
|
+
]).then((it)=>{
|
|
49
|
+
if (it === null) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
stream.controller.enqueue([
|
|
60
53
|
idx,
|
|
61
54
|
PROMISE_STATUS_FULFILLED,
|
|
62
|
-
|
|
55
|
+
dehydrate(it, path)
|
|
63
56
|
]);
|
|
64
|
-
}).catch((
|
|
57
|
+
}).catch((cause)=>{
|
|
65
58
|
opts.onError?.({
|
|
66
|
-
error,
|
|
59
|
+
error: cause,
|
|
67
60
|
path
|
|
68
61
|
});
|
|
69
|
-
enqueue([
|
|
62
|
+
stream.controller.enqueue([
|
|
70
63
|
idx,
|
|
71
64
|
PROMISE_STATUS_REJECTED,
|
|
72
65
|
opts.formatError?.({
|
|
73
|
-
error,
|
|
66
|
+
error: cause,
|
|
74
67
|
path
|
|
75
68
|
})
|
|
76
69
|
]);
|
|
@@ -80,7 +73,7 @@ function createBatchStreamProducer(opts) {
|
|
|
80
73
|
});
|
|
81
74
|
return idx;
|
|
82
75
|
}
|
|
83
|
-
function
|
|
76
|
+
function dehydrateAsyncIterable(iterable, path) {
|
|
84
77
|
const error = checkMaxDepth(path);
|
|
85
78
|
if (error) {
|
|
86
79
|
iterable = {
|
|
@@ -91,37 +84,58 @@ function createBatchStreamProducer(opts) {
|
|
|
91
84
|
}
|
|
92
85
|
const idx = counter++;
|
|
93
86
|
pending.add(idx);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
run(async ()=>{
|
|
88
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
89
|
+
while(true){
|
|
90
|
+
const next = await Promise.race([
|
|
91
|
+
iterator.next().catch(getTRPCErrorFromUnknown),
|
|
92
|
+
stream.cancelledPromise
|
|
93
|
+
]);
|
|
94
|
+
if (next instanceof Error) {
|
|
95
|
+
opts.onError?.({
|
|
96
|
+
error: next,
|
|
97
|
+
path
|
|
98
|
+
});
|
|
99
|
+
stream.controller.enqueue([
|
|
98
100
|
idx,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
ASYNC_ITERABLE_STATUS_ERROR,
|
|
102
|
+
opts.formatError?.({
|
|
103
|
+
error: next,
|
|
104
|
+
path
|
|
105
|
+
})
|
|
101
106
|
]);
|
|
107
|
+
return;
|
|
102
108
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
if (next === 'cancelled') {
|
|
110
|
+
await iterator.return?.();
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
if (next.done) {
|
|
114
|
+
stream.controller.enqueue([
|
|
115
|
+
idx,
|
|
116
|
+
ASYNC_ITERABLE_STATUS_DONE
|
|
117
|
+
]);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
stream.controller.enqueue([
|
|
113
121
|
idx,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
error,
|
|
117
|
-
path
|
|
118
|
-
})
|
|
122
|
+
ASYNC_ITERABLE_STATUS_VALUE,
|
|
123
|
+
dehydrate(next.value, path)
|
|
119
124
|
]);
|
|
120
|
-
} finally{
|
|
121
|
-
pending.delete(idx);
|
|
122
|
-
maybeClose();
|
|
123
125
|
}
|
|
124
|
-
|
|
126
|
+
pending.delete(idx);
|
|
127
|
+
maybeClose();
|
|
128
|
+
}).catch((cause)=>{
|
|
129
|
+
// this shouldn't happen, but node crashes if we don't catch it
|
|
130
|
+
opts.onError?.({
|
|
131
|
+
error: new Error('You found a bug - please report it on https://github.com/trpc/trpc', // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
132
|
+
// @ts-ignore https://github.com/tc39/proposal-error-cause
|
|
133
|
+
{
|
|
134
|
+
cause
|
|
135
|
+
}),
|
|
136
|
+
path
|
|
137
|
+
});
|
|
138
|
+
});
|
|
125
139
|
return idx;
|
|
126
140
|
}
|
|
127
141
|
function checkMaxDepth(path) {
|
|
@@ -130,11 +144,11 @@ function createBatchStreamProducer(opts) {
|
|
|
130
144
|
}
|
|
131
145
|
return null;
|
|
132
146
|
}
|
|
133
|
-
function
|
|
147
|
+
function dehydrateChunk(value, path) {
|
|
134
148
|
if (isPromise(value)) {
|
|
135
149
|
return [
|
|
136
150
|
CHUNK_VALUE_TYPE_PROMISE,
|
|
137
|
-
|
|
151
|
+
dehydratePromise(value, path)
|
|
138
152
|
];
|
|
139
153
|
}
|
|
140
154
|
if (isAsyncIterable(value)) {
|
|
@@ -143,13 +157,13 @@ function createBatchStreamProducer(opts) {
|
|
|
143
157
|
}
|
|
144
158
|
return [
|
|
145
159
|
CHUNK_VALUE_TYPE_ASYNC_ITERABLE,
|
|
146
|
-
|
|
160
|
+
dehydrateAsyncIterable(value, path)
|
|
147
161
|
];
|
|
148
162
|
}
|
|
149
163
|
return null;
|
|
150
164
|
}
|
|
151
|
-
function
|
|
152
|
-
const reg =
|
|
165
|
+
function dehydrate(value, path) {
|
|
166
|
+
const reg = dehydrateChunk(value, path);
|
|
153
167
|
if (reg) {
|
|
154
168
|
return [
|
|
155
169
|
[
|
|
@@ -171,7 +185,7 @@ function createBatchStreamProducer(opts) {
|
|
|
171
185
|
const newObj = {};
|
|
172
186
|
const asyncValues = [];
|
|
173
187
|
for (const [key, item] of Object.entries(value)){
|
|
174
|
-
const transformed =
|
|
188
|
+
const transformed = dehydrateChunk(item, [
|
|
175
189
|
...path,
|
|
176
190
|
key
|
|
177
191
|
]);
|
|
@@ -194,13 +208,13 @@ function createBatchStreamProducer(opts) {
|
|
|
194
208
|
}
|
|
195
209
|
const newHead = {};
|
|
196
210
|
for (const [key, item] of Object.entries(data)){
|
|
197
|
-
newHead[key] =
|
|
211
|
+
newHead[key] = dehydrate(item, [
|
|
198
212
|
key
|
|
199
213
|
]);
|
|
200
214
|
}
|
|
201
215
|
return [
|
|
202
216
|
newHead,
|
|
203
|
-
stream
|
|
217
|
+
stream.readable
|
|
204
218
|
];
|
|
205
219
|
}
|
|
206
220
|
/**
|
|
@@ -244,7 +258,7 @@ class AsyncError extends Error {
|
|
|
244
258
|
const nodeJsStreamToReaderEsque = (source)=>{
|
|
245
259
|
return {
|
|
246
260
|
getReader () {
|
|
247
|
-
const
|
|
261
|
+
const { readable , controller } = createReadableStream();
|
|
248
262
|
source.on('data', (chunk)=>{
|
|
249
263
|
controller.enqueue(chunk);
|
|
250
264
|
});
|
|
@@ -254,7 +268,7 @@ const nodeJsStreamToReaderEsque = (source)=>{
|
|
|
254
268
|
source.on('error', (error)=>{
|
|
255
269
|
controller.error(error);
|
|
256
270
|
});
|
|
257
|
-
return
|
|
271
|
+
return readable.getReader();
|
|
258
272
|
}
|
|
259
273
|
};
|
|
260
274
|
};
|
|
@@ -300,19 +314,6 @@ function createConsumerStream(from) {
|
|
|
300
314
|
}
|
|
301
315
|
}));
|
|
302
316
|
}
|
|
303
|
-
function createDeferred() {
|
|
304
|
-
let resolve;
|
|
305
|
-
let reject;
|
|
306
|
-
const promise = new Promise((res, rej)=>{
|
|
307
|
-
resolve = res;
|
|
308
|
-
reject = rej;
|
|
309
|
-
});
|
|
310
|
-
return {
|
|
311
|
-
promise,
|
|
312
|
-
resolve: resolve,
|
|
313
|
-
reject: reject
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
317
|
/**
|
|
317
318
|
* JSON Lines stream consumer
|
|
318
319
|
* @see https://jsonlines.org/
|
|
@@ -329,9 +330,9 @@ function createDeferred() {
|
|
|
329
330
|
let headDeferred = createDeferred();
|
|
330
331
|
const chunkDeferred = new Map();
|
|
331
332
|
const controllers = new Map();
|
|
332
|
-
function
|
|
333
|
+
function hydrateChunkDefinition(value) {
|
|
333
334
|
const [_path, type, chunkId] = value;
|
|
334
|
-
const
|
|
335
|
+
const { readable , controller } = createReadableStream();
|
|
335
336
|
controllers.set(chunkId, controller);
|
|
336
337
|
// resolve chunk deferred if it exists
|
|
337
338
|
const deferred = chunkDeferred.get(chunkId);
|
|
@@ -344,7 +345,7 @@ function createDeferred() {
|
|
|
344
345
|
{
|
|
345
346
|
return new Promise((resolve, reject)=>{
|
|
346
347
|
// listen for next value in the stream
|
|
347
|
-
const reader =
|
|
348
|
+
const reader = readable.getReader();
|
|
348
349
|
reader.read().then((it)=>{
|
|
349
350
|
if (it.done) {
|
|
350
351
|
reject(new Error('Promise chunk ended without value'));
|
|
@@ -358,7 +359,7 @@ function createDeferred() {
|
|
|
358
359
|
const [_chunkId, status, data] = value;
|
|
359
360
|
switch(status){
|
|
360
361
|
case PROMISE_STATUS_FULFILLED:
|
|
361
|
-
resolve(
|
|
362
|
+
resolve(hydrate(data));
|
|
362
363
|
break;
|
|
363
364
|
case PROMISE_STATUS_REJECTED:
|
|
364
365
|
reject(opts.formatError?.({
|
|
@@ -376,7 +377,7 @@ function createDeferred() {
|
|
|
376
377
|
{
|
|
377
378
|
return {
|
|
378
379
|
[Symbol.asyncIterator]: async function*() {
|
|
379
|
-
const reader =
|
|
380
|
+
const reader = readable.getReader();
|
|
380
381
|
while(true){
|
|
381
382
|
const { done , value } = await reader.read();
|
|
382
383
|
if (done) {
|
|
@@ -388,7 +389,7 @@ function createDeferred() {
|
|
|
388
389
|
const [_chunkId, status, data] = value;
|
|
389
390
|
switch(status){
|
|
390
391
|
case ASYNC_ITERABLE_STATUS_VALUE:
|
|
391
|
-
yield
|
|
392
|
+
yield hydrate(data);
|
|
392
393
|
break;
|
|
393
394
|
case ASYNC_ITERABLE_STATUS_DONE:
|
|
394
395
|
controllers.delete(chunkId);
|
|
@@ -405,15 +406,15 @@ function createDeferred() {
|
|
|
405
406
|
}
|
|
406
407
|
}
|
|
407
408
|
}
|
|
408
|
-
function
|
|
409
|
+
function hydrate(value) {
|
|
409
410
|
const [[data], ...asyncProps] = value;
|
|
410
411
|
for (const value1 of asyncProps){
|
|
411
|
-
const
|
|
412
|
+
const hydrated = hydrateChunkDefinition(value1);
|
|
412
413
|
const [path] = value1;
|
|
413
414
|
if (path === null) {
|
|
414
|
-
return
|
|
415
|
+
return hydrated;
|
|
415
416
|
}
|
|
416
|
-
data[path] =
|
|
417
|
+
data[path] = hydrated;
|
|
417
418
|
}
|
|
418
419
|
return data;
|
|
419
420
|
}
|
|
@@ -435,7 +436,7 @@ function createDeferred() {
|
|
|
435
436
|
if (headDeferred) {
|
|
436
437
|
const head = chunkOrHead;
|
|
437
438
|
for (const [key, value] of Object.entries(chunkOrHead)){
|
|
438
|
-
const parsed =
|
|
439
|
+
const parsed = hydrate(value);
|
|
439
440
|
head[key] = parsed;
|
|
440
441
|
}
|
|
441
442
|
headDeferred.resolve(head);
|