@trpc/server 11.0.0-rc.633 → 11.0.0-rc.638
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 +1 -1
- package/dist/adapters/next-app-dir/redirect.mjs +1 -1
- 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.js +1 -1
- package/dist/adapters/node-http/writeResponse.mjs +1 -1
- package/dist/adapters/standalone.js +1 -1
- package/dist/adapters/standalone.mjs +1 -1
- package/dist/adapters/ws.js +1 -1
- package/dist/adapters/ws.mjs +1 -1
- package/dist/bundle-analysis.json +63 -63
- 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/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/clientish/serialize.d.ts +1 -1
- package/dist/unstable-core-do-not-import/clientish/serialize.d.ts.map +1 -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 +0 -1
- package/dist/unstable-core-do-not-import/http/resolveResponse.mjs +0 -1
- package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +2 -2
- package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/jsonl.d.ts +1 -1
- package/dist/unstable-core-do-not-import/stream/jsonl.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/jsonl.js +73 -47
- package/dist/unstable-core-do-not-import/stream/jsonl.mjs +73 -47
- package/dist/unstable-core-do-not-import/stream/sse.d.ts +0 -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 +2 -4
- package/dist/unstable-core-do-not-import/stream/sse.mjs +2 -4
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts +0 -2
- 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 +5 -8
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.mjs +3 -6
- package/dist/unstable-core-do-not-import/stream/utils/{disposablePromiseTimer.d.ts → timerResource.d.ts} +2 -2
- package/dist/unstable-core-do-not-import/stream/utils/timerResource.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/{disposablePromiseTimer.js → timerResource.js} +2 -2
- package/dist/unstable-core-do-not-import/stream/utils/{disposablePromiseTimer.mjs → timerResource.mjs} +2 -2
- 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 +3 -3
- package/dist/unstable-core-do-not-import/stream/utils/withPing.mjs +2 -2
- package/package.json +4 -3
- package/src/unstable-core-do-not-import/clientish/serialize.ts +1 -1
- package/src/unstable-core-do-not-import/http/resolveResponse.ts +0 -1
- package/src/unstable-core-do-not-import/procedureBuilder.ts +10 -9
- package/src/unstable-core-do-not-import/stream/jsonl.ts +81 -51
- package/src/unstable-core-do-not-import/stream/sse.ts +1 -3
- package/src/unstable-core-do-not-import/stream/utils/asyncIterable.ts +5 -11
- package/src/unstable-core-do-not-import/stream/utils/{disposablePromiseTimer.ts → timerResource.ts} +1 -1
- package/src/unstable-core-do-not-import/stream/utils/withPing.ts +2 -5
- package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts +0 -7
- package/dist/unstable-core-do-not-import/stream/utils/createServer.d.ts.map +0 -1
- package/dist/unstable-core-do-not-import/stream/utils/disposablePromiseTimer.d.ts.map +0 -1
- package/src/unstable-core-do-not-import/stream/utils/createServer.ts +0 -44
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Unpromise } from '../../../vendor/unpromise/unpromise.mjs';
|
|
2
|
-
import { disposablePromiseTimerResult,
|
|
2
|
+
import { disposablePromiseTimerResult, timerResource } from './timerResource.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Derives a new {@link AsyncGenerator} based on {@link iterable}, that automatically stops after the specified duration.
|
|
6
6
|
*/ async function* withMaxDuration(iterable, opts) {
|
|
7
7
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
8
|
-
const timer =
|
|
8
|
+
const timer = timerResource(opts.maxDurationMs);
|
|
9
9
|
try {
|
|
10
10
|
const timerPromise = timer.start();
|
|
11
11
|
// declaration outside the loop for garbage collection reasons
|
|
@@ -17,7 +17,6 @@ import { disposablePromiseTimerResult, disposablePromiseTimer } from './disposab
|
|
|
17
17
|
]);
|
|
18
18
|
if (result === disposablePromiseTimerResult) {
|
|
19
19
|
// cancelled due to timeout
|
|
20
|
-
opts.abortCtrl.abort();
|
|
21
20
|
const res = await iterator.return?.();
|
|
22
21
|
return res?.value;
|
|
23
22
|
}
|
|
@@ -42,7 +41,7 @@ import { disposablePromiseTimerResult, disposablePromiseTimer } from './disposab
|
|
|
42
41
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
43
42
|
// declaration outside the loop for garbage collection reasons
|
|
44
43
|
let result;
|
|
45
|
-
const timer =
|
|
44
|
+
const timer = timerResource(opts.gracePeriodMs);
|
|
46
45
|
try {
|
|
47
46
|
let count = opts.count;
|
|
48
47
|
let timerPromise = new Promise(()=>{
|
|
@@ -64,8 +63,6 @@ import { disposablePromiseTimerResult, disposablePromiseTimer } from './disposab
|
|
|
64
63
|
yield result.value;
|
|
65
64
|
if (--count === 0) {
|
|
66
65
|
timerPromise = timer.start();
|
|
67
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
68
|
-
timerPromise.then(()=>opts.abortCtrl.abort());
|
|
69
66
|
}
|
|
70
67
|
// free up reference for garbage collection
|
|
71
68
|
result = null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const disposablePromiseTimerResult: unique symbol;
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function timerResource(ms: number): {
|
|
3
3
|
start(): Promise<typeof disposablePromiseTimerResult>;
|
|
4
4
|
[Symbol.dispose]: () => void;
|
|
5
5
|
};
|
|
6
|
-
//# sourceMappingURL=
|
|
6
|
+
//# sourceMappingURL=timerResource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timerResource.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/timerResource.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B,eAAW,CAAC;AACrD,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM;;;EAsBvC"}
|
package/dist/unstable-core-do-not-import/stream/utils/{disposablePromiseTimer.js → timerResource.js}
RENAMED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
var _Symbol;
|
|
5
5
|
(_Symbol = Symbol).dispose ?? (_Symbol.dispose = Symbol());
|
|
6
6
|
const disposablePromiseTimerResult = Symbol();
|
|
7
|
-
function
|
|
7
|
+
function timerResource(ms) {
|
|
8
8
|
let timer = null;
|
|
9
9
|
return {
|
|
10
10
|
start () {
|
|
@@ -24,5 +24,5 @@ function disposablePromiseTimer(ms) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
exports.disposablePromiseTimer = disposablePromiseTimer;
|
|
28
27
|
exports.disposablePromiseTimerResult = disposablePromiseTimerResult;
|
|
28
|
+
exports.timerResource = timerResource;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var _Symbol;
|
|
3
3
|
(_Symbol = Symbol).dispose ?? (_Symbol.dispose = Symbol());
|
|
4
4
|
const disposablePromiseTimerResult = Symbol();
|
|
5
|
-
function
|
|
5
|
+
function timerResource(ms) {
|
|
6
6
|
let timer = null;
|
|
7
7
|
return {
|
|
8
8
|
start () {
|
|
@@ -22,4 +22,4 @@ function disposablePromiseTimer(ms) {
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export {
|
|
25
|
+
export { disposablePromiseTimerResult, timerResource };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withPing.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/withPing.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"withPing.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/withPing.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,QAAQ,eAAiB,CAAC;AAEvC;;;GAGG;AACH,wBAAuB,QAAQ,CAAC,MAAM,EACpC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,EAC/B,cAAc,EAAE,MAAM,GACrB,cAAc,CAAC,MAAM,GAAG,OAAO,QAAQ,CAAC,CAmC1C"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var unpromise = require('../../../vendor/unpromise/unpromise.js');
|
|
4
|
-
var
|
|
4
|
+
var timerResource = require('./timerResource.js');
|
|
5
5
|
|
|
6
6
|
const PING_SYM = Symbol('ping');
|
|
7
7
|
/**
|
|
@@ -13,13 +13,13 @@ const PING_SYM = Symbol('ping');
|
|
|
13
13
|
let result;
|
|
14
14
|
let nextPromise = iterator.next();
|
|
15
15
|
while(true){
|
|
16
|
-
const pingPromise =
|
|
16
|
+
const pingPromise = timerResource.timerResource(pingIntervalMs);
|
|
17
17
|
try {
|
|
18
18
|
result = await unpromise.Unpromise.race([
|
|
19
19
|
nextPromise,
|
|
20
20
|
pingPromise.start()
|
|
21
21
|
]);
|
|
22
|
-
if (result ===
|
|
22
|
+
if (result === timerResource.disposablePromiseTimerResult) {
|
|
23
23
|
// cancelled
|
|
24
24
|
yield PING_SYM;
|
|
25
25
|
continue;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Unpromise } from '../../../vendor/unpromise/unpromise.mjs';
|
|
2
|
-
import { disposablePromiseTimerResult,
|
|
2
|
+
import { disposablePromiseTimerResult, timerResource } from './timerResource.mjs';
|
|
3
3
|
|
|
4
4
|
const PING_SYM = Symbol('ping');
|
|
5
5
|
/**
|
|
@@ -11,7 +11,7 @@ const PING_SYM = Symbol('ping');
|
|
|
11
11
|
let result;
|
|
12
12
|
let nextPromise = iterator.next();
|
|
13
13
|
while(true){
|
|
14
|
-
const pingPromise =
|
|
14
|
+
const pingPromise = timerResource(pingIntervalMs);
|
|
15
15
|
try {
|
|
16
16
|
result = await Unpromise.race([
|
|
17
17
|
nextPromise,
|
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.638+09a76869e",
|
|
4
4
|
"description": "The tRPC server library",
|
|
5
5
|
"author": "KATT",
|
|
6
6
|
"license": "MIT",
|
|
@@ -110,7 +110,8 @@
|
|
|
110
110
|
"rpc",
|
|
111
111
|
"shared",
|
|
112
112
|
"unstable-core-do-not-import",
|
|
113
|
-
"!**/*.test.*"
|
|
113
|
+
"!**/*.test.*",
|
|
114
|
+
"!**/__tests__"
|
|
114
115
|
],
|
|
115
116
|
"publishConfig": {
|
|
116
117
|
"access": "public"
|
|
@@ -156,5 +157,5 @@
|
|
|
156
157
|
"next": "*",
|
|
157
158
|
"ws": "*"
|
|
158
159
|
},
|
|
159
|
-
"gitHead": "
|
|
160
|
+
"gitHead": "09a76869e7b1c0b56db4b5bc20ef7cde3015cbdb"
|
|
160
161
|
}
|
|
@@ -26,7 +26,7 @@ type IsRecord<T extends object> = keyof WithoutIndexSignature<T> extends never
|
|
|
26
26
|
export type Serialize<T> =
|
|
27
27
|
IsAny<T> extends true ? any :
|
|
28
28
|
unknown extends T ? unknown :
|
|
29
|
-
T extends
|
|
29
|
+
T extends AsyncIterable<infer $T, infer $Return, infer $Next> ? AsyncIterable<Serialize<$T>, Serialize<$Return>, Serialize<$Next>> :
|
|
30
30
|
T extends JsonReturnable ? T :
|
|
31
31
|
T extends Map<any, any> | Set<any> ? object :
|
|
32
32
|
T extends NonJsonPrimitive ? never :
|
|
@@ -466,7 +466,6 @@ export async function resolveResponse<TRouter extends AnyRouter>(
|
|
|
466
466
|
const stream = sseStreamProducer({
|
|
467
467
|
...config.sse,
|
|
468
468
|
data: iterable,
|
|
469
|
-
abortCtrl: result?.abortCtrl ?? new AbortController(),
|
|
470
469
|
serialize: (v) => config.transformer.output.serialize(v),
|
|
471
470
|
formatError(errorOpts) {
|
|
472
471
|
const error = getTRPCErrorFromUnknown(errorOpts.error);
|
|
@@ -44,21 +44,22 @@ type DefaultValue<TValue, TFallback> = TValue extends UnsetMarker
|
|
|
44
44
|
? TFallback
|
|
45
45
|
: TValue;
|
|
46
46
|
|
|
47
|
-
type
|
|
48
|
-
TOutput extends
|
|
47
|
+
type inferAsyncIterable<TOutput> =
|
|
48
|
+
TOutput extends AsyncIterable<infer $Yield, infer $Return, infer $Next>
|
|
49
49
|
? {
|
|
50
50
|
yield: $Yield;
|
|
51
51
|
return: $Return;
|
|
52
52
|
next: $Next;
|
|
53
53
|
}
|
|
54
54
|
: never;
|
|
55
|
-
type inferSubscriptionOutput<TOutput> =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
type inferSubscriptionOutput<TOutput> =
|
|
56
|
+
TOutput extends AsyncIterable<any>
|
|
57
|
+
? AsyncIterable<
|
|
58
|
+
inferTrackedOutput<inferAsyncIterable<TOutput>['yield']>,
|
|
59
|
+
inferAsyncIterable<TOutput>['return'],
|
|
60
|
+
inferAsyncIterable<TOutput>['next']
|
|
61
|
+
>
|
|
62
|
+
: TypeError<'Subscription output could not be inferred'>;
|
|
62
63
|
|
|
63
64
|
export type CallerOverride<TContext> = (opts: {
|
|
64
65
|
args: unknown[];
|
|
@@ -425,13 +425,20 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
425
425
|
|
|
426
426
|
type ControllerChunk = ChunkData | StreamInterruptedError;
|
|
427
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>>();
|
|
428
433
|
|
|
429
|
-
const controllers =
|
|
430
|
-
|
|
431
|
-
|
|
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
|
|
432
439
|
opts.abortController?.abort();
|
|
433
|
-
}
|
|
434
|
-
|
|
440
|
+
}
|
|
441
|
+
};
|
|
435
442
|
|
|
436
443
|
function decodeChunkDefinition(value: ChunkDefinition) {
|
|
437
444
|
const [_path, type, chunkId] = value;
|
|
@@ -440,6 +447,13 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
440
447
|
|
|
441
448
|
controllers.set(chunkId, stream.controller);
|
|
442
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
|
+
}
|
|
456
|
+
|
|
443
457
|
switch (type) {
|
|
444
458
|
case CHUNK_VALUE_TYPE_PROMISE: {
|
|
445
459
|
return new Promise((resolve, reject) => {
|
|
@@ -473,60 +487,66 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
473
487
|
.catch(reject)
|
|
474
488
|
.finally(() => {
|
|
475
489
|
controllers.delete(chunkId);
|
|
490
|
+
maybeAbort();
|
|
476
491
|
});
|
|
477
492
|
});
|
|
478
493
|
}
|
|
479
494
|
case CHUNK_VALUE_TYPE_ASYNC_ITERABLE: {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
controllers.delete(chunkId);
|
|
507
|
-
return {
|
|
508
|
-
done: true,
|
|
509
|
-
value: decode(data),
|
|
510
|
-
};
|
|
511
|
-
case ASYNC_ITERABLE_STATUS_ERROR:
|
|
512
|
-
controllers.delete(chunkId);
|
|
513
|
-
throw (
|
|
514
|
-
opts.formatError?.({ error: data }) ??
|
|
515
|
-
new AsyncError(data)
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
|
-
},
|
|
519
|
-
return: async () => {
|
|
495
|
+
const reader = stream.readable.getReader();
|
|
496
|
+
const iterator: AsyncIterator<unknown> = {
|
|
497
|
+
next: async () => {
|
|
498
|
+
const { done, value } = await reader.read();
|
|
499
|
+
if (value instanceof StreamInterruptedError) {
|
|
500
|
+
throw value;
|
|
501
|
+
}
|
|
502
|
+
if (done) {
|
|
503
|
+
controllers.delete(chunkId);
|
|
504
|
+
maybeAbort();
|
|
505
|
+
|
|
506
|
+
return {
|
|
507
|
+
done: true,
|
|
508
|
+
value: undefined,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const [_chunkId, status, data] = value as IterableChunk;
|
|
513
|
+
|
|
514
|
+
switch (status) {
|
|
515
|
+
case ASYNC_ITERABLE_STATUS_VALUE:
|
|
516
|
+
return {
|
|
517
|
+
done: false,
|
|
518
|
+
value: decode(data),
|
|
519
|
+
};
|
|
520
|
+
case ASYNC_ITERABLE_STATUS_RETURN:
|
|
520
521
|
controllers.delete(chunkId);
|
|
522
|
+
maybeAbort();
|
|
523
|
+
|
|
521
524
|
return {
|
|
522
525
|
done: true,
|
|
523
|
-
value:
|
|
526
|
+
value: decode(data),
|
|
524
527
|
};
|
|
525
|
-
|
|
528
|
+
case ASYNC_ITERABLE_STATUS_ERROR:
|
|
529
|
+
controllers.delete(chunkId);
|
|
530
|
+
maybeAbort();
|
|
531
|
+
|
|
532
|
+
throw (
|
|
533
|
+
opts.formatError?.({ error: data }) ?? new AsyncError(data)
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
return: async () => {
|
|
538
|
+
controllers.delete(chunkId);
|
|
539
|
+
maybeAbort();
|
|
540
|
+
|
|
541
|
+
return {
|
|
542
|
+
done: true,
|
|
543
|
+
value: undefined,
|
|
526
544
|
};
|
|
527
|
-
return iterator;
|
|
528
545
|
},
|
|
529
546
|
};
|
|
547
|
+
return {
|
|
548
|
+
[Symbol.asyncIterator]: () => iterator,
|
|
549
|
+
};
|
|
530
550
|
}
|
|
531
551
|
}
|
|
532
552
|
}
|
|
@@ -571,19 +591,29 @@ export async function jsonlStreamConsumer<THead>(opts: {
|
|
|
571
591
|
headDeferred.resolve(head as THead);
|
|
572
592
|
headDeferred = null;
|
|
573
593
|
|
|
574
|
-
controllers.activate();
|
|
575
594
|
return;
|
|
576
595
|
}
|
|
577
596
|
const chunk = chunkOrHead as ChunkData;
|
|
578
597
|
const [idx] = chunk;
|
|
579
598
|
|
|
580
599
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
581
|
-
|
|
582
|
-
|
|
600
|
+
let readController = controllers.get(idx)!;
|
|
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);
|
|
583
610
|
},
|
|
584
611
|
close: closeOrAbort,
|
|
585
612
|
abort: closeOrAbort,
|
|
586
613
|
}),
|
|
614
|
+
{
|
|
615
|
+
signal: opts.abortController.signal,
|
|
616
|
+
},
|
|
587
617
|
)
|
|
588
618
|
.catch((error) => {
|
|
589
619
|
opts.onError?.({ error });
|
|
@@ -32,7 +32,7 @@ export interface PingOptions {
|
|
|
32
32
|
export interface SSEStreamProducerOptions<TValue = unknown> {
|
|
33
33
|
serialize?: Serialize;
|
|
34
34
|
data: AsyncIterable<TValue>;
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
maxDepth?: number;
|
|
37
37
|
ping?: PingOptions;
|
|
38
38
|
/**
|
|
@@ -85,7 +85,6 @@ export function sseStreamProducer<TValue = unknown>(
|
|
|
85
85
|
iterable = takeWithGrace(iterable, {
|
|
86
86
|
count: 1,
|
|
87
87
|
gracePeriodMs: 1,
|
|
88
|
-
abortCtrl: opts.abortCtrl,
|
|
89
88
|
});
|
|
90
89
|
}
|
|
91
90
|
|
|
@@ -96,7 +95,6 @@ export function sseStreamProducer<TValue = unknown>(
|
|
|
96
95
|
) {
|
|
97
96
|
iterable = withMaxDuration(iterable, {
|
|
98
97
|
maxDurationMs: opts.maxDurationMs,
|
|
99
|
-
abortCtrl: opts.abortCtrl,
|
|
100
98
|
});
|
|
101
99
|
}
|
|
102
100
|
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import { Unpromise } from '../../../vendor/unpromise';
|
|
2
|
-
import {
|
|
3
|
-
disposablePromiseTimer,
|
|
4
|
-
disposablePromiseTimerResult,
|
|
5
|
-
} from './disposablePromiseTimer';
|
|
2
|
+
import { disposablePromiseTimerResult, timerResource } from './timerResource';
|
|
6
3
|
|
|
7
4
|
/**
|
|
8
5
|
* Derives a new {@link AsyncGenerator} based on {@link iterable}, that automatically stops after the specified duration.
|
|
9
6
|
*/
|
|
10
7
|
export async function* withMaxDuration<T>(
|
|
11
8
|
iterable: AsyncIterable<T>,
|
|
12
|
-
opts: { maxDurationMs: number
|
|
9
|
+
opts: { maxDurationMs: number },
|
|
13
10
|
): AsyncGenerator<T> {
|
|
14
11
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
15
12
|
|
|
16
|
-
const timer =
|
|
13
|
+
const timer = timerResource(opts.maxDurationMs);
|
|
17
14
|
try {
|
|
18
15
|
const timerPromise = timer.start();
|
|
19
16
|
|
|
@@ -24,7 +21,7 @@ export async function* withMaxDuration<T>(
|
|
|
24
21
|
result = await Unpromise.race([iterator.next(), timerPromise]);
|
|
25
22
|
if (result === disposablePromiseTimerResult) {
|
|
26
23
|
// cancelled due to timeout
|
|
27
|
-
|
|
24
|
+
|
|
28
25
|
const res = await iterator.return?.();
|
|
29
26
|
return res?.value;
|
|
30
27
|
}
|
|
@@ -52,7 +49,6 @@ export async function* takeWithGrace<T>(
|
|
|
52
49
|
opts: {
|
|
53
50
|
count: number;
|
|
54
51
|
gracePeriodMs: number;
|
|
55
|
-
abortCtrl: AbortController;
|
|
56
52
|
},
|
|
57
53
|
): AsyncGenerator<T> {
|
|
58
54
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
@@ -60,7 +56,7 @@ export async function* takeWithGrace<T>(
|
|
|
60
56
|
// declaration outside the loop for garbage collection reasons
|
|
61
57
|
let result: null | IteratorResult<T> | typeof disposablePromiseTimerResult;
|
|
62
58
|
|
|
63
|
-
const timer =
|
|
59
|
+
const timer = timerResource(opts.gracePeriodMs);
|
|
64
60
|
try {
|
|
65
61
|
let count = opts.count;
|
|
66
62
|
|
|
@@ -81,8 +77,6 @@ export async function* takeWithGrace<T>(
|
|
|
81
77
|
yield result.value;
|
|
82
78
|
if (--count === 0) {
|
|
83
79
|
timerPromise = timer.start();
|
|
84
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
85
|
-
timerPromise.then(() => opts.abortCtrl.abort());
|
|
86
80
|
}
|
|
87
81
|
// free up reference for garbage collection
|
|
88
82
|
result = null;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { Unpromise } from '../../../vendor/unpromise';
|
|
2
|
-
import {
|
|
3
|
-
disposablePromiseTimer,
|
|
4
|
-
disposablePromiseTimerResult,
|
|
5
|
-
} from './disposablePromiseTimer';
|
|
2
|
+
import { disposablePromiseTimerResult, timerResource } from './timerResource';
|
|
6
3
|
|
|
7
4
|
export const PING_SYM = Symbol('ping');
|
|
8
5
|
|
|
@@ -23,7 +20,7 @@ export async function* withPing<TValue>(
|
|
|
23
20
|
|
|
24
21
|
let nextPromise = iterator.next();
|
|
25
22
|
while (true) {
|
|
26
|
-
const pingPromise =
|
|
23
|
+
const pingPromise = timerResource(pingIntervalMs);
|
|
27
24
|
|
|
28
25
|
try {
|
|
29
26
|
result = await Unpromise.race([nextPromise, pingPromise.start()]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createServer.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/createServer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,wBAAgB,YAAY,CAC1B,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI;;;;EAuCvE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"disposablePromiseTimer.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/disposablePromiseTimer.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B,eAAW,CAAC;AACrD,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM;;;EAsBhD"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import http from 'http';
|
|
2
|
-
import type { Socket } from 'net';
|
|
3
|
-
|
|
4
|
-
export function createServer(
|
|
5
|
-
handler: (req: http.IncomingMessage, res: http.ServerResponse) => void,
|
|
6
|
-
) {
|
|
7
|
-
const server = http.createServer(async (req, res) => {
|
|
8
|
-
handler(req, res);
|
|
9
|
-
});
|
|
10
|
-
server.listen(0);
|
|
11
|
-
|
|
12
|
-
const connections = new Set<Socket>();
|
|
13
|
-
server.on('connection', (conn) => {
|
|
14
|
-
connections.add(conn);
|
|
15
|
-
conn.once('close', () => {
|
|
16
|
-
connections.delete(conn);
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
const port = (server.address() as any).port;
|
|
21
|
-
|
|
22
|
-
const url = `http://localhost:${port}`;
|
|
23
|
-
|
|
24
|
-
async function forceClose() {
|
|
25
|
-
for (const conn of connections) {
|
|
26
|
-
conn.destroy();
|
|
27
|
-
}
|
|
28
|
-
await new Promise((resolve) => {
|
|
29
|
-
server.close(resolve);
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
url,
|
|
35
|
-
close: async () => {
|
|
36
|
-
await forceClose();
|
|
37
|
-
},
|
|
38
|
-
restart: async () => {
|
|
39
|
-
await forceClose();
|
|
40
|
-
|
|
41
|
-
server.listen(port);
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
}
|