@trpc/server 11.0.0-rc.643 → 11.0.0-rc.648
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/adapters/aws-lambda/index.js +1 -1
- package/dist/adapters/aws-lambda/index.mjs +1 -1
- package/dist/adapters/express.js +1 -1
- package/dist/adapters/express.mjs +1 -1
- package/dist/adapters/fastify/fastifyRequestHandler.js +1 -1
- package/dist/adapters/fastify/fastifyRequestHandler.mjs +1 -1
- package/dist/adapters/fetch/fetchRequestHandler.js +1 -1
- package/dist/adapters/fetch/fetchRequestHandler.mjs +1 -1
- package/dist/adapters/next-app-dir/nextAppDirCaller.js +1 -1
- package/dist/adapters/next-app-dir/nextAppDirCaller.mjs +1 -1
- package/dist/adapters/next-app-dir/notFound.js +1 -1
- package/dist/adapters/next-app-dir/notFound.mjs +1 -1
- package/dist/adapters/next-app-dir/redirect.js +15 -3
- package/dist/adapters/next-app-dir/redirect.mjs +14 -2
- package/dist/adapters/next.js +1 -1
- package/dist/adapters/next.mjs +1 -1
- package/dist/adapters/node-http/incomingMessageToRequest.js +1 -1
- package/dist/adapters/node-http/incomingMessageToRequest.mjs +1 -1
- package/dist/adapters/node-http/nodeHTTPRequestHandler.js +1 -1
- package/dist/adapters/node-http/nodeHTTPRequestHandler.mjs +1 -1
- package/dist/adapters/node-http/writeResponse.d.ts.map +1 -1
- package/dist/adapters/node-http/writeResponse.js +3 -1
- package/dist/adapters/node-http/writeResponse.mjs +3 -1
- package/dist/adapters/standalone.js +1 -1
- package/dist/adapters/standalone.mjs +1 -1
- package/dist/adapters/ws.d.ts.map +1 -1
- package/dist/adapters/ws.js +145 -66
- package/dist/adapters/ws.mjs +145 -66
- package/dist/bundle-analysis.json +194 -201
- package/dist/http.js +1 -1
- package/dist/http.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.1_rollup@4.27.4_tslib@2.8.1_typescript@5.6.2/node_modules/tslib/tslib.es6.js +73 -0
- package/dist/observable/observable.d.ts +1 -1
- package/dist/observable/observable.d.ts.map +1 -1
- package/dist/observable/observable.js +16 -4
- package/dist/observable/observable.mjs +16 -4
- package/dist/rpc.js +1 -1
- package/dist/rpc.mjs +1 -1
- package/dist/shared.js +1 -1
- package/dist/shared.mjs +1 -1
- package/dist/unstable-core-do-not-import/error/TRPCError.d.ts +1 -1
- package/dist/unstable-core-do-not-import/error/TRPCError.js +14 -2
- package/dist/unstable-core-do-not-import/error/TRPCError.mjs +13 -1
- package/dist/unstable-core-do-not-import/http/resolveResponse.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/http/resolveResponse.js +7 -18
- package/dist/unstable-core-do-not-import/http/resolveResponse.mjs +8 -19
- package/dist/unstable-core-do-not-import/stream/jsonl.d.ts +15 -4
- package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/jsonl.js +430 -291
- package/dist/unstable-core-do-not-import/stream/jsonl.mjs +428 -289
- package/dist/unstable-core-do-not-import/stream/sse.d.ts +1 -1
- package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/sse.js +183 -122
- package/dist/unstable-core-do-not-import/stream/sse.mjs +183 -122
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.js +103 -10
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.mjs +104 -12
- package/dist/unstable-core-do-not-import/stream/utils/disposable.d.ts +17 -0
- package/dist/unstable-core-do-not-import/stream/utils/disposable.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/disposable.js +44 -0
- package/dist/unstable-core-do-not-import/stream/utils/disposable.mjs +41 -0
- package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.d.ts +8 -0
- package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.js +25 -0
- package/dist/unstable-core-do-not-import/stream/utils/readableStreamFrom.mjs +23 -0
- package/dist/unstable-core-do-not-import/stream/utils/timerResource.d.ts +1 -2
- package/dist/unstable-core-do-not-import/stream/utils/timerResource.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/utils/timerResource.js +8 -10
- package/dist/unstable-core-do-not-import/stream/utils/timerResource.mjs +8 -10
- package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/utils/withPing.js +113 -24
- package/dist/unstable-core-do-not-import/stream/utils/withPing.mjs +114 -25
- package/dist/unstable-core-do-not-import/transformer.d.ts +1 -1
- package/dist/unstable-core-do-not-import.d.ts +1 -0
- package/dist/unstable-core-do-not-import.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import.js +3 -0
- package/dist/unstable-core-do-not-import.mjs +1 -0
- package/dist/vendor/unpromise/unpromise.js +17 -6
- package/dist/vendor/unpromise/unpromise.mjs +13 -2
- package/package.json +2 -3
- package/src/adapters/node-http/writeResponse.ts +3 -0
- package/src/adapters/ws.ts +8 -9
- package/src/observable/observable.ts +17 -2
- package/src/unstable-core-do-not-import/http/resolveResponse.ts +8 -21
- package/src/unstable-core-do-not-import/stream/jsonl.ts +236 -216
- package/src/unstable-core-do-not-import/stream/sse.ts +112 -132
- package/src/unstable-core-do-not-import/stream/utils/asyncIterable.ts +50 -48
- package/src/unstable-core-do-not-import/stream/utils/disposable.ts +52 -0
- package/src/unstable-core-do-not-import/stream/utils/readableStreamFrom.ts +28 -0
- package/src/unstable-core-do-not-import/stream/utils/timerResource.ts +17 -15
- package/src/unstable-core-do-not-import/stream/utils/withPing.ts +18 -19
- package/src/unstable-core-do-not-import.ts +1 -0
- package/dist/node_modules/.pnpm/@swc_helpers@0.5.13/node_modules/@swc/helpers/esm/_define_property.js +0 -11
- package/dist/node_modules/.pnpm/@swc_helpers@0.5.13/node_modules/@swc/helpers/esm/_define_property.mjs +0 -9
- package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts +0 -9
- package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.d.ts.map +0 -1
- package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.js +0 -25
- package/dist/unstable-core-do-not-import/stream/utils/createReadableStream.mjs +0 -23
- package/dist/unstable-core-do-not-import/stream/utils/withRefCount.d.ts +0 -17
- package/dist/unstable-core-do-not-import/stream/utils/withRefCount.d.ts.map +0 -1
- package/dist/unstable-core-do-not-import/stream/utils/withRefCount.js +0 -59
- package/dist/unstable-core-do-not-import/stream/utils/withRefCount.mjs +0 -57
- package/src/unstable-core-do-not-import/stream/utils/createReadableStream.ts +0 -25
- package/src/unstable-core-do-not-import/stream/utils/withRefCount.ts +0 -93
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { Unpromise } from '../../vendor/unpromise';
|
|
1
2
|
import { isAsyncIterable, isFunction, isObject, run } from '../utils';
|
|
3
|
+
import { iteratorResource } from './utils/asyncIterable';
|
|
2
4
|
import type { Deferred } from './utils/createDeferred';
|
|
3
5
|
import { createDeferred } from './utils/createDeferred';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
+
import { makeAsyncResource, makeResource } from './utils/disposable';
|
|
7
|
+
import { readableStreamFrom } from './utils/readableStreamFrom';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* A subset of the standard ReadableStream properties needed by tRPC internally.
|
|
@@ -19,6 +21,8 @@ export type NodeJSReadableStreamEsque = {
|
|
|
19
21
|
): NodeJSReadableStreamEsque;
|
|
20
22
|
};
|
|
21
23
|
|
|
24
|
+
// ---------- types
|
|
25
|
+
|
|
22
26
|
// ---------- types
|
|
23
27
|
const CHUNK_VALUE_TYPE_PROMISE = 0;
|
|
24
28
|
type CHUNK_VALUE_TYPE_PROMISE = typeof CHUNK_VALUE_TYPE_PROMISE;
|
|
@@ -32,8 +36,8 @@ type PROMISE_STATUS_REJECTED = typeof PROMISE_STATUS_REJECTED;
|
|
|
32
36
|
|
|
33
37
|
const ASYNC_ITERABLE_STATUS_RETURN = 0;
|
|
34
38
|
type ASYNC_ITERABLE_STATUS_RETURN = typeof ASYNC_ITERABLE_STATUS_RETURN;
|
|
35
|
-
const
|
|
36
|
-
type
|
|
39
|
+
const ASYNC_ITERABLE_STATUS_YIELD = 1;
|
|
40
|
+
type ASYNC_ITERABLE_STATUS_YIELD = typeof ASYNC_ITERABLE_STATUS_YIELD;
|
|
37
41
|
const ASYNC_ITERABLE_STATUS_ERROR = 2;
|
|
38
42
|
type ASYNC_ITERABLE_STATUS_ERROR = typeof ASYNC_ITERABLE_STATUS_ERROR;
|
|
39
43
|
|
|
@@ -77,7 +81,7 @@ type IterableChunk =
|
|
|
77
81
|
]
|
|
78
82
|
| [
|
|
79
83
|
chunkIndex: ChunkIndex,
|
|
80
|
-
status:
|
|
84
|
+
status: ASYNC_ITERABLE_STATUS_YIELD,
|
|
81
85
|
value: EncodedValue,
|
|
82
86
|
]
|
|
83
87
|
| [
|
|
@@ -117,101 +121,98 @@ class MaxDepthError extends Error {
|
|
|
117
121
|
}
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
function createBatchStreamProducer(
|
|
124
|
+
async function* createBatchStreamProducer(
|
|
125
|
+
opts: ProducerOptions,
|
|
126
|
+
): AsyncIterable<Head | ChunkData, void> {
|
|
121
127
|
const { data } = opts;
|
|
122
128
|
let counter = 0 as ChunkIndex;
|
|
123
129
|
const placeholder = 0 as PlaceholderValue;
|
|
124
130
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
+
await using queue = makeAsyncResource(
|
|
132
|
+
new Set<{
|
|
133
|
+
iterator: AsyncIterator<ChunkData, ChunkData>;
|
|
134
|
+
nextPromise: Promise<IteratorResult<ChunkData, ChunkData>>;
|
|
135
|
+
}>(),
|
|
136
|
+
async () => {
|
|
137
|
+
await Promise.all(Array.from(queue).map((it) => it.iterator.return?.()));
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
function registerAsync(
|
|
141
|
+
callback: (idx: ChunkIndex) => AsyncIterable<ChunkData, ChunkData>,
|
|
142
|
+
) {
|
|
143
|
+
const idx = counter++ as ChunkIndex;
|
|
131
144
|
|
|
132
|
-
|
|
133
|
-
if (!stream.cancelled()) {
|
|
134
|
-
stream.controller.enqueue(chunk);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
145
|
+
const iterator = callback(idx)[Symbol.asyncIterator]();
|
|
137
146
|
|
|
138
|
-
|
|
139
|
-
const error = checkMaxDepth(path);
|
|
140
|
-
if (error) {
|
|
141
|
-
// Catch any errors from the original promise to ensure they're reported
|
|
142
|
-
promise.catch((cause) => {
|
|
143
|
-
opts.onError?.({ error: cause, path });
|
|
144
|
-
});
|
|
145
|
-
// Replace the promise with a rejected one containing the max depth error
|
|
146
|
-
promise = Promise.reject(error);
|
|
147
|
-
}
|
|
148
|
-
const idx = counter++ as ChunkIndex;
|
|
149
|
-
pending.add(idx);
|
|
147
|
+
const nextPromise = iterator.next();
|
|
150
148
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
nextPromise.catch(() => {
|
|
150
|
+
// prevent unhandled promise rejection
|
|
151
|
+
});
|
|
152
|
+
queue.add({
|
|
153
|
+
iterator,
|
|
154
|
+
nextPromise,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
return idx;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function encodePromise(promise: Promise<unknown>, path: (string | number)[]) {
|
|
161
|
+
return registerAsync(async function* (idx) {
|
|
162
|
+
const error = checkMaxDepth(path);
|
|
163
|
+
if (error) {
|
|
164
|
+
// Catch any errors from the original promise to ensure they're reported
|
|
165
|
+
promise.catch((cause) => {
|
|
166
|
+
opts.onError?.({ error: cause, path });
|
|
167
|
+
});
|
|
168
|
+
// Replace the promise with a rejected one containing the max depth error
|
|
169
|
+
promise = Promise.reject(error);
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const next = await promise;
|
|
173
|
+
return [idx, PROMISE_STATUS_FULFILLED, encode(next, path)];
|
|
174
|
+
} catch (cause) {
|
|
156
175
|
opts.onError?.({ error: cause, path });
|
|
157
|
-
|
|
176
|
+
return [
|
|
158
177
|
idx,
|
|
159
178
|
PROMISE_STATUS_REJECTED,
|
|
160
179
|
opts.formatError?.({ error: cause, path }),
|
|
161
|
-
]
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
pending.delete(idx);
|
|
165
|
-
});
|
|
166
|
-
return idx;
|
|
180
|
+
];
|
|
181
|
+
}
|
|
182
|
+
});
|
|
167
183
|
}
|
|
168
184
|
function encodeAsyncIterable(
|
|
169
185
|
iterable: AsyncIterable<unknown>,
|
|
170
186
|
path: (string | number)[],
|
|
171
187
|
) {
|
|
172
|
-
|
|
173
|
-
pending.add(idx);
|
|
174
|
-
run(async () => {
|
|
188
|
+
return registerAsync(async function* (idx) {
|
|
175
189
|
const error = checkMaxDepth(path);
|
|
176
190
|
if (error) {
|
|
177
191
|
throw error;
|
|
178
192
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
encode(next.value, path),
|
|
193
|
-
]);
|
|
194
|
-
break;
|
|
193
|
+
await using iterator = iteratorResource(iterable);
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
while (true) {
|
|
197
|
+
const next = await iterator.next();
|
|
198
|
+
if (next.done) {
|
|
199
|
+
return [
|
|
200
|
+
idx,
|
|
201
|
+
ASYNC_ITERABLE_STATUS_RETURN,
|
|
202
|
+
encode(next.value, path),
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
yield [idx, ASYNC_ITERABLE_STATUS_YIELD, encode(next.value, path)];
|
|
195
206
|
}
|
|
196
|
-
|
|
197
|
-
idx,
|
|
198
|
-
ASYNC_ITERABLE_STATUS_VALUE,
|
|
199
|
-
encode(next.value, path),
|
|
200
|
-
]);
|
|
201
|
-
}
|
|
202
|
-
})
|
|
203
|
-
.catch((cause) => {
|
|
207
|
+
} catch (cause) {
|
|
204
208
|
opts.onError?.({ error: cause, path });
|
|
205
|
-
|
|
209
|
+
return [
|
|
206
210
|
idx,
|
|
207
211
|
ASYNC_ITERABLE_STATUS_ERROR,
|
|
208
212
|
opts.formatError?.({ error: cause, path }),
|
|
209
|
-
]
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
pending.delete(idx);
|
|
213
|
-
});
|
|
214
|
-
return idx;
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
});
|
|
215
216
|
}
|
|
216
217
|
function checkMaxDepth(path: (string | number)[]) {
|
|
217
218
|
if (opts.maxDepth && path.length > opts.maxDepth) {
|
|
@@ -266,20 +267,35 @@ function createBatchStreamProducer(opts: ProducerOptions) {
|
|
|
266
267
|
for (const [key, item] of Object.entries(data)) {
|
|
267
268
|
newHead[key] = encode(item, [key]);
|
|
268
269
|
}
|
|
269
|
-
pending.activate();
|
|
270
270
|
|
|
271
|
-
|
|
271
|
+
yield newHead;
|
|
272
|
+
|
|
273
|
+
// Process all async iterables in parallel by racing their next values
|
|
274
|
+
while (queue.size > 0) {
|
|
275
|
+
// Race all iterators to get the next value from any of them
|
|
276
|
+
const [entry, res] = await Unpromise.race(
|
|
277
|
+
Array.from(queue).map(async (it) => [it, await it.nextPromise] as const),
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
yield res.value;
|
|
281
|
+
|
|
282
|
+
// Remove current iterator and re-add if not done
|
|
283
|
+
queue.delete(entry);
|
|
284
|
+
if (!res.done) {
|
|
285
|
+
entry.nextPromise = entry.iterator.next();
|
|
286
|
+
queue.add(entry);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
272
289
|
}
|
|
273
290
|
/**
|
|
274
291
|
* JSON Lines stream producer
|
|
275
292
|
* @see https://jsonlines.org/
|
|
276
293
|
*/
|
|
277
294
|
export function jsonlStreamProducer(opts: ProducerOptions) {
|
|
278
|
-
let
|
|
295
|
+
let stream = readableStreamFrom(createBatchStreamProducer(opts));
|
|
279
296
|
|
|
280
297
|
const { serialize } = opts;
|
|
281
298
|
if (serialize) {
|
|
282
|
-
head = serialize(head);
|
|
283
299
|
stream = stream.pipeThrough(
|
|
284
300
|
new TransformStream({
|
|
285
301
|
transform(chunk, controller) {
|
|
@@ -292,9 +308,6 @@ export function jsonlStreamProducer(opts: ProducerOptions) {
|
|
|
292
308
|
return stream
|
|
293
309
|
.pipeThrough(
|
|
294
310
|
new TransformStream({
|
|
295
|
-
start(controller) {
|
|
296
|
-
controller.enqueue(JSON.stringify(head) + '\n');
|
|
297
|
-
},
|
|
298
311
|
transform(chunk, controller) {
|
|
299
312
|
controller.enqueue(JSON.stringify(chunk) + '\n');
|
|
300
313
|
},
|
|
@@ -320,17 +333,20 @@ export type ConsumerOnError = (opts: { error: unknown }) => void;
|
|
|
320
333
|
const nodeJsStreamToReaderEsque = (source: NodeJSReadableStreamEsque) => {
|
|
321
334
|
return {
|
|
322
335
|
getReader() {
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
336
|
+
const stream = new ReadableStream<Uint8Array>({
|
|
337
|
+
start(controller) {
|
|
338
|
+
source.on('data', (chunk) => {
|
|
339
|
+
controller.enqueue(chunk);
|
|
340
|
+
});
|
|
341
|
+
source.on('end', () => {
|
|
342
|
+
controller.close();
|
|
343
|
+
});
|
|
344
|
+
source.on('error', (error) => {
|
|
345
|
+
controller.error(error);
|
|
346
|
+
});
|
|
347
|
+
},
|
|
332
348
|
});
|
|
333
|
-
return
|
|
349
|
+
return stream.getReader();
|
|
334
350
|
},
|
|
335
351
|
};
|
|
336
352
|
};
|
|
@@ -394,6 +410,102 @@ function createConsumerStream<THead>(
|
|
|
394
410
|
}),
|
|
395
411
|
);
|
|
396
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Represents a chunk of data or stream interruption error that can be enqueued to a controller
|
|
415
|
+
*/
|
|
416
|
+
type ControllerChunk = ChunkData | StreamInterruptedError;
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Creates a handler for managing stream controllers and their lifecycle
|
|
420
|
+
*/
|
|
421
|
+
function createStreamsManager(abortController: AbortController) {
|
|
422
|
+
const controllerMap = new Map<
|
|
423
|
+
ChunkIndex,
|
|
424
|
+
ReturnType<typeof createStreamController>
|
|
425
|
+
>();
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Checks if there are no pending controllers or deferred promises
|
|
429
|
+
*/
|
|
430
|
+
function isEmpty() {
|
|
431
|
+
return Array.from(controllerMap.values()).every((c) => c.closed);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Creates a stream controller
|
|
436
|
+
*/
|
|
437
|
+
function createStreamController() {
|
|
438
|
+
let originalController: ReadableStreamDefaultController<ControllerChunk>;
|
|
439
|
+
const stream = new ReadableStream<ControllerChunk>({
|
|
440
|
+
start(controller) {
|
|
441
|
+
originalController = controller;
|
|
442
|
+
},
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const streamController = {
|
|
446
|
+
enqueue: (v: ControllerChunk) => originalController.enqueue(v),
|
|
447
|
+
close: () => {
|
|
448
|
+
originalController.close();
|
|
449
|
+
|
|
450
|
+
// mark as closed and remove methods
|
|
451
|
+
Object.assign(streamController, {
|
|
452
|
+
closed: true,
|
|
453
|
+
close: () => {
|
|
454
|
+
// noop
|
|
455
|
+
},
|
|
456
|
+
enqueue: () => {
|
|
457
|
+
// noop
|
|
458
|
+
},
|
|
459
|
+
getReaderResource: null,
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
if (isEmpty()) {
|
|
463
|
+
abortController.abort();
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
closed: false,
|
|
467
|
+
getReaderResource: () => {
|
|
468
|
+
const reader = stream.getReader();
|
|
469
|
+
|
|
470
|
+
return makeResource(reader, () => {
|
|
471
|
+
reader.releaseLock();
|
|
472
|
+
streamController.close();
|
|
473
|
+
});
|
|
474
|
+
},
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
return streamController;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Gets or creates a stream controller
|
|
482
|
+
*/
|
|
483
|
+
function getOrCreate(chunkId: ChunkIndex) {
|
|
484
|
+
let c = controllerMap.get(chunkId);
|
|
485
|
+
if (!c) {
|
|
486
|
+
c = createStreamController();
|
|
487
|
+
controllerMap.set(chunkId, c);
|
|
488
|
+
}
|
|
489
|
+
return c;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Cancels all pending controllers and rejects deferred promises
|
|
494
|
+
*/
|
|
495
|
+
function cancelAll(reason: unknown) {
|
|
496
|
+
const error = new StreamInterruptedError(reason);
|
|
497
|
+
for (const controller of controllerMap.values()) {
|
|
498
|
+
controller.enqueue(error);
|
|
499
|
+
controller.close();
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return {
|
|
504
|
+
getOrCreate,
|
|
505
|
+
isEmpty,
|
|
506
|
+
cancelAll,
|
|
507
|
+
};
|
|
508
|
+
}
|
|
397
509
|
|
|
398
510
|
/**
|
|
399
511
|
* JSON Lines stream consumer
|
|
@@ -423,130 +535,56 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
423
535
|
}
|
|
424
536
|
let headDeferred: null | Deferred<THead> = createDeferred();
|
|
425
537
|
|
|
426
|
-
|
|
427
|
-
type ChunkController = ReadableStreamDefaultController<ControllerChunk>;
|
|
428
|
-
/**
|
|
429
|
-
* This is needed as new values can come in before the controller has read the chunk
|
|
430
|
-
* Not pretty, could likely be refactored and omitted somehow
|
|
431
|
-
*/
|
|
432
|
-
const chunkDeferred = new Map<ChunkIndex, Deferred<ChunkController>>();
|
|
433
|
-
|
|
434
|
-
const controllers = new Map<ChunkIndex, ChunkController>();
|
|
435
|
-
|
|
436
|
-
const maybeAbort = () => {
|
|
437
|
-
if (chunkDeferred.size === 0 && controllers.size === 0) {
|
|
438
|
-
// nothing is listening to the stream anymore
|
|
439
|
-
opts.abortController?.abort();
|
|
440
|
-
}
|
|
441
|
-
};
|
|
538
|
+
const streamManager = createStreamsManager(opts.abortController);
|
|
442
539
|
|
|
443
540
|
function decodeChunkDefinition(value: ChunkDefinition) {
|
|
444
541
|
const [_path, type, chunkId] = value;
|
|
445
542
|
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
controllers.set(chunkId, stream.controller);
|
|
449
|
-
|
|
450
|
-
// resolve chunk deferred if it exists
|
|
451
|
-
const deferred = chunkDeferred.get(chunkId);
|
|
452
|
-
if (deferred) {
|
|
453
|
-
deferred.resolve(stream.controller);
|
|
454
|
-
chunkDeferred.delete(chunkId);
|
|
455
|
-
}
|
|
543
|
+
const controller = streamManager.getOrCreate(chunkId);
|
|
456
544
|
|
|
457
545
|
switch (type) {
|
|
458
546
|
case CHUNK_VALUE_TYPE_PROMISE: {
|
|
459
|
-
return
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
reader
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
const value = it.value;
|
|
474
|
-
const [_chunkId, status, data] = value as PromiseChunk;
|
|
475
|
-
switch (status) {
|
|
476
|
-
case PROMISE_STATUS_FULFILLED:
|
|
477
|
-
resolve(decode(data));
|
|
478
|
-
|
|
479
|
-
break;
|
|
480
|
-
case PROMISE_STATUS_REJECTED:
|
|
481
|
-
reject(
|
|
482
|
-
opts.formatError?.({ error: data }) ?? new AsyncError(data),
|
|
483
|
-
);
|
|
484
|
-
break;
|
|
485
|
-
}
|
|
486
|
-
})
|
|
487
|
-
.catch(reject)
|
|
488
|
-
.finally(() => {
|
|
489
|
-
controllers.delete(chunkId);
|
|
490
|
-
maybeAbort();
|
|
491
|
-
});
|
|
547
|
+
return run(async () => {
|
|
548
|
+
using reader = controller.getReaderResource();
|
|
549
|
+
|
|
550
|
+
const { value } = await reader.read();
|
|
551
|
+
if (value instanceof StreamInterruptedError) {
|
|
552
|
+
throw value;
|
|
553
|
+
}
|
|
554
|
+
const [_chunkId, status, data] = value as PromiseChunk;
|
|
555
|
+
switch (status) {
|
|
556
|
+
case PROMISE_STATUS_FULFILLED:
|
|
557
|
+
return decode(data);
|
|
558
|
+
case PROMISE_STATUS_REJECTED:
|
|
559
|
+
throw opts.formatError?.({ error: data }) ?? new AsyncError(data);
|
|
560
|
+
}
|
|
492
561
|
});
|
|
493
562
|
}
|
|
494
563
|
case CHUNK_VALUE_TYPE_ASYNC_ITERABLE: {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
564
|
+
return run(async function* () {
|
|
565
|
+
using reader = controller.getReaderResource();
|
|
566
|
+
|
|
567
|
+
while (true) {
|
|
568
|
+
const { value } = await reader.read();
|
|
499
569
|
if (value instanceof StreamInterruptedError) {
|
|
500
570
|
throw value;
|
|
501
571
|
}
|
|
502
|
-
if (done) {
|
|
503
|
-
controllers.delete(chunkId);
|
|
504
|
-
maybeAbort();
|
|
505
|
-
|
|
506
|
-
return {
|
|
507
|
-
done: true,
|
|
508
|
-
value: undefined,
|
|
509
|
-
};
|
|
510
|
-
}
|
|
511
572
|
|
|
512
573
|
const [_chunkId, status, data] = value as IterableChunk;
|
|
513
574
|
|
|
514
575
|
switch (status) {
|
|
515
|
-
case
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
value: decode(data),
|
|
519
|
-
};
|
|
576
|
+
case ASYNC_ITERABLE_STATUS_YIELD:
|
|
577
|
+
yield decode(data);
|
|
578
|
+
break;
|
|
520
579
|
case ASYNC_ITERABLE_STATUS_RETURN:
|
|
521
|
-
|
|
522
|
-
maybeAbort();
|
|
523
|
-
|
|
524
|
-
return {
|
|
525
|
-
done: true,
|
|
526
|
-
value: decode(data),
|
|
527
|
-
};
|
|
580
|
+
return decode(data);
|
|
528
581
|
case ASYNC_ITERABLE_STATUS_ERROR:
|
|
529
|
-
controllers.delete(chunkId);
|
|
530
|
-
maybeAbort();
|
|
531
|
-
|
|
532
582
|
throw (
|
|
533
583
|
opts.formatError?.({ error: data }) ?? new AsyncError(data)
|
|
534
584
|
);
|
|
535
585
|
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
controllers.delete(chunkId);
|
|
539
|
-
maybeAbort();
|
|
540
|
-
|
|
541
|
-
return {
|
|
542
|
-
done: true,
|
|
543
|
-
value: undefined,
|
|
544
|
-
};
|
|
545
|
-
},
|
|
546
|
-
};
|
|
547
|
-
return {
|
|
548
|
-
[Symbol.asyncIterator]: () => iterator,
|
|
549
|
-
};
|
|
586
|
+
}
|
|
587
|
+
});
|
|
550
588
|
}
|
|
551
589
|
}
|
|
552
590
|
}
|
|
@@ -571,16 +609,12 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
571
609
|
const error = new StreamInterruptedError(reason);
|
|
572
610
|
|
|
573
611
|
headDeferred?.reject(error);
|
|
574
|
-
|
|
575
|
-
controller.enqueue(error);
|
|
576
|
-
controller.close();
|
|
577
|
-
}
|
|
578
|
-
controllers.clear();
|
|
612
|
+
streamManager.cancelAll(error);
|
|
579
613
|
};
|
|
580
614
|
source
|
|
581
615
|
.pipeTo(
|
|
582
616
|
new WritableStream({
|
|
583
|
-
|
|
617
|
+
write(chunkOrHead) {
|
|
584
618
|
if (headDeferred) {
|
|
585
619
|
const head = chunkOrHead as Record<number | string, unknown>;
|
|
586
620
|
|
|
@@ -596,17 +630,8 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
596
630
|
const chunk = chunkOrHead as ChunkData;
|
|
597
631
|
const [idx] = chunk;
|
|
598
632
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
if (!readController) {
|
|
602
|
-
let deferred = chunkDeferred.get(idx);
|
|
603
|
-
if (!deferred) {
|
|
604
|
-
deferred = createDeferred();
|
|
605
|
-
chunkDeferred.set(idx, deferred);
|
|
606
|
-
}
|
|
607
|
-
readController = await deferred.promise;
|
|
608
|
-
}
|
|
609
|
-
readController.enqueue(chunk);
|
|
633
|
+
const controller = streamManager.getOrCreate(idx);
|
|
634
|
+
controller.enqueue(chunk);
|
|
610
635
|
},
|
|
611
636
|
close: closeOrAbort,
|
|
612
637
|
abort: closeOrAbort,
|
|
@@ -620,10 +645,5 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
620
645
|
closeOrAbort(error);
|
|
621
646
|
});
|
|
622
647
|
|
|
623
|
-
return [
|
|
624
|
-
await headDeferred.promise,
|
|
625
|
-
{
|
|
626
|
-
controllers,
|
|
627
|
-
},
|
|
628
|
-
] as const;
|
|
648
|
+
return [await headDeferred.promise, streamManager] as const;
|
|
629
649
|
}
|