@trpc/server 11.0.0-rc.571 → 11.0.0-rc.577
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/bundle-analysis.json +129 -80
- package/dist/unstable-core-do-not-import/stream/sse.d.ts +3 -3
- package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/sse.js +53 -65
- package/dist/unstable-core-do-not-import/stream/sse.mjs +55 -67
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts +17 -0
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.js +59 -0
- package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.mjs +56 -0
- package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts +0 -11
- package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/stream/utils/createDeferred.js +0 -29
- package/dist/unstable-core-do-not-import/stream/utils/createDeferred.mjs +1 -29
- package/dist/unstable-core-do-not-import/stream/utils/promiseTimer.d.ts +8 -0
- package/dist/unstable-core-do-not-import/stream/utils/promiseTimer.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/promiseTimer.js +38 -0
- package/dist/unstable-core-do-not-import/stream/utils/promiseTimer.mjs +36 -0
- package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts +7 -0
- package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts.map +1 -0
- package/dist/unstable-core-do-not-import/stream/utils/withPing.js +37 -0
- package/dist/unstable-core-do-not-import/stream/utils/withPing.mjs +34 -0
- package/dist/unstable-core-do-not-import/utils.d.ts +2 -0
- package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
- package/dist/unstable-core-do-not-import/utils.js +7 -0
- package/dist/unstable-core-do-not-import/utils.mjs +6 -1
- package/dist/unstable-core-do-not-import.js +2 -1
- package/dist/unstable-core-do-not-import.mjs +2 -2
- package/package.json +3 -3
- package/src/unstable-core-do-not-import/stream/sse.ts +60 -91
- package/src/unstable-core-do-not-import/stream/utils/asyncIterable.ts +62 -0
- package/src/unstable-core-do-not-import/stream/utils/createDeferred.ts +0 -36
- package/src/unstable-core-do-not-import/stream/utils/promiseTimer.ts +40 -0
- package/src/unstable-core-do-not-import/stream/utils/withPing.ts +35 -0
- package/src/unstable-core-do-not-import/utils.ts +7 -0
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
var TRPCError = require('../error/TRPCError.js');
|
|
4
4
|
var utils = require('../utils.js');
|
|
5
5
|
var tracked = require('./tracked.js');
|
|
6
|
+
var asyncIterable = require('./utils/asyncIterable.js');
|
|
6
7
|
var createDeferred = require('./utils/createDeferred.js');
|
|
7
8
|
var createReadableStream = require('./utils/createReadableStream.js');
|
|
9
|
+
var promiseTimer = require('./utils/promiseTimer.js');
|
|
10
|
+
var withPing = require('./utils/withPing.js');
|
|
8
11
|
|
|
9
12
|
const SERIALIZED_ERROR_EVENT = 'serialized-error';
|
|
10
13
|
/**
|
|
@@ -15,83 +18,68 @@ const SERIALIZED_ERROR_EVENT = 'serialized-error';
|
|
|
15
18
|
stream.controller.enqueue({
|
|
16
19
|
comment: 'connected'
|
|
17
20
|
});
|
|
18
|
-
const { serialize =
|
|
21
|
+
const { serialize =utils.identity } = opts;
|
|
19
22
|
const ping = {
|
|
20
23
|
enabled: opts.ping?.enabled ?? false,
|
|
21
24
|
intervalMs: opts.ping?.intervalMs ?? 1000
|
|
22
25
|
};
|
|
23
26
|
utils.run(async ()=>{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
27
|
+
let iterable = opts.data;
|
|
28
|
+
iterable = asyncIterable.withCancel(iterable, stream.cancelledPromise);
|
|
29
|
+
if (opts.emitAndEndImmediately) {
|
|
30
|
+
iterable = asyncIterable.takeWithGrace(iterable, {
|
|
31
|
+
count: 1,
|
|
32
|
+
gracePeriodMs: 1
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
let maxDurationTimer = null;
|
|
36
|
+
if (opts.maxDurationMs != null && opts.maxDurationMs > 0 && opts.maxDurationMs !== Infinity) {
|
|
37
|
+
maxDurationTimer = promiseTimer.createPromiseTimer(opts.maxDurationMs).start();
|
|
38
|
+
iterable = asyncIterable.withCancel(iterable, maxDurationTimer.promise);
|
|
39
|
+
}
|
|
40
|
+
if (ping.enabled && ping.intervalMs !== Infinity && ping.intervalMs > 0) {
|
|
41
|
+
iterable = withPing.withPing(iterable, ping.intervalMs);
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
for await (const value of iterable){
|
|
45
|
+
if (value === withPing.PING_SYM) {
|
|
46
|
+
stream.controller.enqueue({
|
|
47
|
+
comment: 'ping'
|
|
48
|
+
});
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const chunk = tracked.isTrackedEnvelope(value) ? {
|
|
52
|
+
id: value[0],
|
|
53
|
+
data: value[1]
|
|
54
|
+
} : {
|
|
55
|
+
data: value
|
|
56
|
+
};
|
|
57
|
+
if ('data' in chunk) {
|
|
58
|
+
chunk.data = JSON.stringify(serialize(chunk.data));
|
|
59
|
+
}
|
|
60
|
+
stream.controller.enqueue(chunk);
|
|
57
61
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
} catch (err) {
|
|
63
|
+
// ignore abort errors, send any other errors
|
|
64
|
+
if (!(err instanceof Error) || err.name !== 'AbortError') {
|
|
65
|
+
// `err` must be caused by `opts.data`, `JSON.stringify` or `serialize`.
|
|
66
|
+
// So, a user error in any case.
|
|
67
|
+
const error = TRPCError.getTRPCErrorFromUnknown(err);
|
|
68
|
+
const data = opts.formatError?.({
|
|
69
|
+
error
|
|
70
|
+
}) ?? null;
|
|
62
71
|
stream.controller.enqueue({
|
|
63
72
|
event: SERIALIZED_ERROR_EVENT,
|
|
64
73
|
data: JSON.stringify(serialize(data))
|
|
65
74
|
});
|
|
66
|
-
break;
|
|
67
75
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
const value = next.value;
|
|
72
|
-
const chunk = tracked.isTrackedEnvelope(value) ? {
|
|
73
|
-
id: value[0],
|
|
74
|
-
data: value[1]
|
|
75
|
-
} : {
|
|
76
|
-
data: value
|
|
77
|
-
};
|
|
78
|
-
if ('data' in chunk) {
|
|
79
|
-
chunk.data = JSON.stringify(serialize(chunk.data));
|
|
80
|
-
}
|
|
81
|
-
stream.controller.enqueue(chunk);
|
|
82
|
-
if (opts.emitAndEndImmediately) {
|
|
83
|
-
// end the stream in the next tick so that we can send a few more events from the queue
|
|
84
|
-
setTimeout(maxDurationPromise.resolve, 1);
|
|
85
|
-
}
|
|
86
|
-
nextPromise = iterator.next();
|
|
87
|
-
}
|
|
88
|
-
maxDurationPromise.clear();
|
|
89
|
-
await iterator.return?.();
|
|
90
|
-
try {
|
|
76
|
+
} finally{
|
|
77
|
+
maxDurationTimer?.clear();
|
|
91
78
|
stream.controller.close();
|
|
92
|
-
}
|
|
93
|
-
}).catch((
|
|
94
|
-
|
|
79
|
+
}
|
|
80
|
+
}).catch((err)=>{
|
|
81
|
+
// should not be reached; just in case...
|
|
82
|
+
stream.controller.error(err);
|
|
95
83
|
});
|
|
96
84
|
return stream.readable.pipeThrough(new TransformStream({
|
|
97
85
|
transform (chunk, controller) {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { getTRPCErrorFromUnknown } from '../error/TRPCError.mjs';
|
|
2
|
-
import { run } from '../utils.mjs';
|
|
2
|
+
import { run, identity } from '../utils.mjs';
|
|
3
3
|
import { isTrackedEnvelope } from './tracked.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { withCancel, takeWithGrace } from './utils/asyncIterable.mjs';
|
|
5
|
+
import { createDeferred } from './utils/createDeferred.mjs';
|
|
5
6
|
import { createReadableStream } from './utils/createReadableStream.mjs';
|
|
7
|
+
import { createPromiseTimer } from './utils/promiseTimer.mjs';
|
|
8
|
+
import { withPing, PING_SYM } from './utils/withPing.mjs';
|
|
6
9
|
|
|
7
10
|
const SERIALIZED_ERROR_EVENT = 'serialized-error';
|
|
8
11
|
/**
|
|
@@ -13,83 +16,68 @@ const SERIALIZED_ERROR_EVENT = 'serialized-error';
|
|
|
13
16
|
stream.controller.enqueue({
|
|
14
17
|
comment: 'connected'
|
|
15
18
|
});
|
|
16
|
-
const { serialize =
|
|
19
|
+
const { serialize =identity } = opts;
|
|
17
20
|
const ping = {
|
|
18
21
|
enabled: opts.ping?.enabled ?? false,
|
|
19
22
|
intervalMs: opts.ping?.intervalMs ?? 1000
|
|
20
23
|
};
|
|
21
24
|
run(async ()=>{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
25
|
+
let iterable = opts.data;
|
|
26
|
+
iterable = withCancel(iterable, stream.cancelledPromise);
|
|
27
|
+
if (opts.emitAndEndImmediately) {
|
|
28
|
+
iterable = takeWithGrace(iterable, {
|
|
29
|
+
count: 1,
|
|
30
|
+
gracePeriodMs: 1
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
let maxDurationTimer = null;
|
|
34
|
+
if (opts.maxDurationMs != null && opts.maxDurationMs > 0 && opts.maxDurationMs !== Infinity) {
|
|
35
|
+
maxDurationTimer = createPromiseTimer(opts.maxDurationMs).start();
|
|
36
|
+
iterable = withCancel(iterable, maxDurationTimer.promise);
|
|
37
|
+
}
|
|
38
|
+
if (ping.enabled && ping.intervalMs !== Infinity && ping.intervalMs > 0) {
|
|
39
|
+
iterable = withPing(iterable, ping.intervalMs);
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
for await (const value of iterable){
|
|
43
|
+
if (value === PING_SYM) {
|
|
44
|
+
stream.controller.enqueue({
|
|
45
|
+
comment: 'ping'
|
|
46
|
+
});
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const chunk = isTrackedEnvelope(value) ? {
|
|
50
|
+
id: value[0],
|
|
51
|
+
data: value[1]
|
|
52
|
+
} : {
|
|
53
|
+
data: value
|
|
54
|
+
};
|
|
55
|
+
if ('data' in chunk) {
|
|
56
|
+
chunk.data = JSON.stringify(serialize(chunk.data));
|
|
57
|
+
}
|
|
58
|
+
stream.controller.enqueue(chunk);
|
|
55
59
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
} catch (err) {
|
|
61
|
+
// ignore abort errors, send any other errors
|
|
62
|
+
if (!(err instanceof Error) || err.name !== 'AbortError') {
|
|
63
|
+
// `err` must be caused by `opts.data`, `JSON.stringify` or `serialize`.
|
|
64
|
+
// So, a user error in any case.
|
|
65
|
+
const error = getTRPCErrorFromUnknown(err);
|
|
66
|
+
const data = opts.formatError?.({
|
|
67
|
+
error
|
|
68
|
+
}) ?? null;
|
|
60
69
|
stream.controller.enqueue({
|
|
61
70
|
event: SERIALIZED_ERROR_EVENT,
|
|
62
71
|
data: JSON.stringify(serialize(data))
|
|
63
72
|
});
|
|
64
|
-
break;
|
|
65
73
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
const value = next.value;
|
|
70
|
-
const chunk = isTrackedEnvelope(value) ? {
|
|
71
|
-
id: value[0],
|
|
72
|
-
data: value[1]
|
|
73
|
-
} : {
|
|
74
|
-
data: value
|
|
75
|
-
};
|
|
76
|
-
if ('data' in chunk) {
|
|
77
|
-
chunk.data = JSON.stringify(serialize(chunk.data));
|
|
78
|
-
}
|
|
79
|
-
stream.controller.enqueue(chunk);
|
|
80
|
-
if (opts.emitAndEndImmediately) {
|
|
81
|
-
// end the stream in the next tick so that we can send a few more events from the queue
|
|
82
|
-
setTimeout(maxDurationPromise.resolve, 1);
|
|
83
|
-
}
|
|
84
|
-
nextPromise = iterator.next();
|
|
85
|
-
}
|
|
86
|
-
maxDurationPromise.clear();
|
|
87
|
-
await iterator.return?.();
|
|
88
|
-
try {
|
|
74
|
+
} finally{
|
|
75
|
+
maxDurationTimer?.clear();
|
|
89
76
|
stream.controller.close();
|
|
90
|
-
}
|
|
91
|
-
}).catch((
|
|
92
|
-
|
|
77
|
+
}
|
|
78
|
+
}).catch((err)=>{
|
|
79
|
+
// should not be reached; just in case...
|
|
80
|
+
stream.controller.error(err);
|
|
93
81
|
});
|
|
94
82
|
return stream.readable.pipeThrough(new TransformStream({
|
|
95
83
|
transform (chunk, controller) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives a new {@link AsyncGenerator} based of {@link iterable}, that automatically stops with the
|
|
3
|
+
* passed {@link cancel} promise.
|
|
4
|
+
*/
|
|
5
|
+
export declare function withCancel<T>(iterable: AsyncIterable<T>, cancel: Promise<unknown>): AsyncGenerator<T>;
|
|
6
|
+
interface TakeWithGraceOptions {
|
|
7
|
+
count: number;
|
|
8
|
+
gracePeriodMs: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Derives a new {@link AsyncGenerator} based of {@link iterable}, that yields its first
|
|
12
|
+
* {@link count} values. Then, a grace period of {@link gracePeriodMs} is started in which further
|
|
13
|
+
* values may still come through. After this period, the generator stops.
|
|
14
|
+
*/
|
|
15
|
+
export declare function takeWithGrace<T>(iterable: AsyncIterable<T>, { count, gracePeriodMs }: TakeWithGraceOptions): AsyncGenerator<T>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=asyncIterable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncIterable.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/asyncIterable.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAuB,UAAU,CAAC,CAAC,EACjC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAC1B,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,GACvB,cAAc,CAAC,CAAC,CAAC,CAcnB;AAED,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAuB,aAAa,CAAC,CAAC,EACpC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAC1B,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,oBAAoB,GAC7C,cAAc,CAAC,CAAC,CAAC,CAsBnB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var utils = require('../../utils.js');
|
|
4
|
+
var promiseTimer = require('./promiseTimer.js');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Derives a new {@link AsyncGenerator} based of {@link iterable}, that automatically stops with the
|
|
8
|
+
* passed {@link cancel} promise.
|
|
9
|
+
*/ async function* withCancel(iterable, cancel) {
|
|
10
|
+
const cancelPromise = cancel.then(utils.noop);
|
|
11
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
12
|
+
while(true){
|
|
13
|
+
const result = await Promise.race([
|
|
14
|
+
iterator.next(),
|
|
15
|
+
cancelPromise
|
|
16
|
+
]);
|
|
17
|
+
if (result == null) {
|
|
18
|
+
await iterator.return?.();
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
if (result.done) {
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
yield result.value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Derives a new {@link AsyncGenerator} based of {@link iterable}, that yields its first
|
|
29
|
+
* {@link count} values. Then, a grace period of {@link gracePeriodMs} is started in which further
|
|
30
|
+
* values may still come through. After this period, the generator stops.
|
|
31
|
+
*/ async function* takeWithGrace(iterable, { count , gracePeriodMs }) {
|
|
32
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
33
|
+
const timer = promiseTimer.createPromiseTimer(gracePeriodMs);
|
|
34
|
+
try {
|
|
35
|
+
while(true){
|
|
36
|
+
const result = await Promise.race([
|
|
37
|
+
iterator.next(),
|
|
38
|
+
timer.promise
|
|
39
|
+
]);
|
|
40
|
+
if (result == null) {
|
|
41
|
+
// cancelled
|
|
42
|
+
await iterator.return?.();
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
if (result.done) {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
yield result.value;
|
|
49
|
+
if (--count === 0) {
|
|
50
|
+
timer.start();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} finally{
|
|
54
|
+
timer.clear();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
exports.takeWithGrace = takeWithGrace;
|
|
59
|
+
exports.withCancel = withCancel;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { noop } from '../../utils.mjs';
|
|
2
|
+
import { createPromiseTimer } from './promiseTimer.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Derives a new {@link AsyncGenerator} based of {@link iterable}, that automatically stops with the
|
|
6
|
+
* passed {@link cancel} promise.
|
|
7
|
+
*/ async function* withCancel(iterable, cancel) {
|
|
8
|
+
const cancelPromise = cancel.then(noop);
|
|
9
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
10
|
+
while(true){
|
|
11
|
+
const result = await Promise.race([
|
|
12
|
+
iterator.next(),
|
|
13
|
+
cancelPromise
|
|
14
|
+
]);
|
|
15
|
+
if (result == null) {
|
|
16
|
+
await iterator.return?.();
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
if (result.done) {
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
yield result.value;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Derives a new {@link AsyncGenerator} based of {@link iterable}, that yields its first
|
|
27
|
+
* {@link count} values. Then, a grace period of {@link gracePeriodMs} is started in which further
|
|
28
|
+
* values may still come through. After this period, the generator stops.
|
|
29
|
+
*/ async function* takeWithGrace(iterable, { count , gracePeriodMs }) {
|
|
30
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
31
|
+
const timer = createPromiseTimer(gracePeriodMs);
|
|
32
|
+
try {
|
|
33
|
+
while(true){
|
|
34
|
+
const result = await Promise.race([
|
|
35
|
+
iterator.next(),
|
|
36
|
+
timer.promise
|
|
37
|
+
]);
|
|
38
|
+
if (result == null) {
|
|
39
|
+
// cancelled
|
|
40
|
+
await iterator.return?.();
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
if (result.done) {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
yield result.value;
|
|
47
|
+
if (--count === 0) {
|
|
48
|
+
timer.start();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} finally{
|
|
52
|
+
timer.clear();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { takeWithGrace, withCancel };
|
|
@@ -4,15 +4,4 @@ export declare function createDeferred<TValue>(): {
|
|
|
4
4
|
reject: (error: unknown) => void;
|
|
5
5
|
};
|
|
6
6
|
export type Deferred<TValue> = ReturnType<typeof createDeferred<TValue>>;
|
|
7
|
-
export declare const createTimeoutPromise: <TValue>(timeoutMs: number, value: TValue) => {
|
|
8
|
-
promise: Promise<TValue>;
|
|
9
|
-
/**
|
|
10
|
-
* Clear the timeout without resolving the promise
|
|
11
|
-
*/
|
|
12
|
-
clear: () => void;
|
|
13
|
-
/**
|
|
14
|
-
* Resolve the promise with the value
|
|
15
|
-
*/
|
|
16
|
-
resolve: () => void;
|
|
17
|
-
};
|
|
18
7
|
//# sourceMappingURL=createDeferred.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDeferred.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/createDeferred.ts"],"names":[],"mappings":"AACA,wBAAgB,cAAc,CAAC,MAAM;;qBACd,MAAM,KAAK,IAAI;oBAChB,OAAO,KAAK,IAAI;EAOrC;AACD,MAAM,MAAM,QAAQ,CAAC,MAAM,IAAI,UAAU,CAAC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC
|
|
1
|
+
{"version":3,"file":"createDeferred.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/createDeferred.ts"],"names":[],"mappings":"AACA,wBAAgB,cAAc,CAAC,MAAM;;qBACd,MAAM,KAAK,IAAI;oBAChB,OAAO,KAAK,IAAI;EAOrC;AACD,MAAM,MAAM,QAAQ,CAAC,MAAM,IAAI,UAAU,CAAC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC"}
|
|
@@ -13,34 +13,5 @@
|
|
|
13
13
|
reject: reject
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
const createTimeoutPromise = (timeoutMs, value)=>{
|
|
17
|
-
let deferred = createDeferred();
|
|
18
|
-
deferred = deferred;
|
|
19
|
-
let timeout = null;
|
|
20
|
-
const clear = ()=>{
|
|
21
|
-
if (timeout) {
|
|
22
|
-
clearTimeout(timeout);
|
|
23
|
-
timeout = null;
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
const resolve = ()=>{
|
|
27
|
-
deferred.resolve(value);
|
|
28
|
-
clear();
|
|
29
|
-
};
|
|
30
|
-
if (timeoutMs !== Infinity) {
|
|
31
|
-
timeout = setTimeout(resolve, timeoutMs);
|
|
32
|
-
timeout.unref?.();
|
|
33
|
-
}
|
|
34
|
-
return {
|
|
35
|
-
promise: deferred.promise,
|
|
36
|
-
/**
|
|
37
|
-
* Clear the timeout without resolving the promise
|
|
38
|
-
*/ clear,
|
|
39
|
-
/**
|
|
40
|
-
* Resolve the promise with the value
|
|
41
|
-
*/ resolve
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
16
|
|
|
45
17
|
exports.createDeferred = createDeferred;
|
|
46
|
-
exports.createTimeoutPromise = createTimeoutPromise;
|
|
@@ -11,33 +11,5 @@
|
|
|
11
11
|
reject: reject
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
-
const createTimeoutPromise = (timeoutMs, value)=>{
|
|
15
|
-
let deferred = createDeferred();
|
|
16
|
-
deferred = deferred;
|
|
17
|
-
let timeout = null;
|
|
18
|
-
const clear = ()=>{
|
|
19
|
-
if (timeout) {
|
|
20
|
-
clearTimeout(timeout);
|
|
21
|
-
timeout = null;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
const resolve = ()=>{
|
|
25
|
-
deferred.resolve(value);
|
|
26
|
-
clear();
|
|
27
|
-
};
|
|
28
|
-
if (timeoutMs !== Infinity) {
|
|
29
|
-
timeout = setTimeout(resolve, timeoutMs);
|
|
30
|
-
timeout.unref?.();
|
|
31
|
-
}
|
|
32
|
-
return {
|
|
33
|
-
promise: deferred.promise,
|
|
34
|
-
/**
|
|
35
|
-
* Clear the timeout without resolving the promise
|
|
36
|
-
*/ clear,
|
|
37
|
-
/**
|
|
38
|
-
* Resolve the promise with the value
|
|
39
|
-
*/ resolve
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
14
|
|
|
43
|
-
export { createDeferred
|
|
15
|
+
export { createDeferred };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function createPromiseTimer(ms: number): {
|
|
2
|
+
readonly promise: Promise<void>;
|
|
3
|
+
start: () => PromiseTimer;
|
|
4
|
+
reset: () => PromiseTimer;
|
|
5
|
+
clear: () => PromiseTimer;
|
|
6
|
+
};
|
|
7
|
+
export type PromiseTimer = ReturnType<typeof createPromiseTimer>;
|
|
8
|
+
//# sourceMappingURL=promiseTimer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promiseTimer.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/promiseTimer.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM;;iBAezB,YAAY;iBAQZ,YAAY;iBAMZ,YAAY;EAO/B;AACD,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var createDeferred = require('./createDeferred.js');
|
|
4
|
+
|
|
5
|
+
function createPromiseTimer(ms) {
|
|
6
|
+
let deferred = createDeferred.createDeferred();
|
|
7
|
+
let timeout = null;
|
|
8
|
+
const timer = {
|
|
9
|
+
get promise () {
|
|
10
|
+
return deferred.promise;
|
|
11
|
+
},
|
|
12
|
+
start,
|
|
13
|
+
reset,
|
|
14
|
+
clear
|
|
15
|
+
};
|
|
16
|
+
return timer;
|
|
17
|
+
function start() {
|
|
18
|
+
if (timeout != null) {
|
|
19
|
+
throw new Error("PromiseTimer already started.");
|
|
20
|
+
}
|
|
21
|
+
timeout = setTimeout(deferred.resolve, ms);
|
|
22
|
+
return timer;
|
|
23
|
+
}
|
|
24
|
+
function reset() {
|
|
25
|
+
clear();
|
|
26
|
+
deferred = createDeferred.createDeferred();
|
|
27
|
+
return timer;
|
|
28
|
+
}
|
|
29
|
+
function clear() {
|
|
30
|
+
if (timeout != null) {
|
|
31
|
+
clearTimeout(timeout);
|
|
32
|
+
timeout = null;
|
|
33
|
+
}
|
|
34
|
+
return timer;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
exports.createPromiseTimer = createPromiseTimer;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createDeferred } from './createDeferred.mjs';
|
|
2
|
+
|
|
3
|
+
function createPromiseTimer(ms) {
|
|
4
|
+
let deferred = createDeferred();
|
|
5
|
+
let timeout = null;
|
|
6
|
+
const timer = {
|
|
7
|
+
get promise () {
|
|
8
|
+
return deferred.promise;
|
|
9
|
+
},
|
|
10
|
+
start,
|
|
11
|
+
reset,
|
|
12
|
+
clear
|
|
13
|
+
};
|
|
14
|
+
return timer;
|
|
15
|
+
function start() {
|
|
16
|
+
if (timeout != null) {
|
|
17
|
+
throw new Error("PromiseTimer already started.");
|
|
18
|
+
}
|
|
19
|
+
timeout = setTimeout(deferred.resolve, ms);
|
|
20
|
+
return timer;
|
|
21
|
+
}
|
|
22
|
+
function reset() {
|
|
23
|
+
clear();
|
|
24
|
+
deferred = createDeferred();
|
|
25
|
+
return timer;
|
|
26
|
+
}
|
|
27
|
+
function clear() {
|
|
28
|
+
if (timeout != null) {
|
|
29
|
+
clearTimeout(timeout);
|
|
30
|
+
timeout = null;
|
|
31
|
+
}
|
|
32
|
+
return timer;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { createPromiseTimer };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const PING_SYM: unique symbol;
|
|
2
|
+
/**
|
|
3
|
+
* Derives a new {@link AsyncGenerator} based of {@link iterable}, that yields {@link PING_SYM}
|
|
4
|
+
* whenever no value has been yielded for {@link pingIntervalMs}.
|
|
5
|
+
*/
|
|
6
|
+
export declare function withPing<TValue>(iterable: AsyncIterable<TValue>, pingIntervalMs: number): AsyncGenerator<TValue | typeof PING_SYM>;
|
|
7
|
+
//# sourceMappingURL=withPing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withPing.d.ts","sourceRoot":"","sources":["../../../../src/unstable-core-do-not-import/stream/utils/withPing.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ,eAAiB,CAAC;AAOvC;;;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,CAkB1C"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var promiseTimer = require('./promiseTimer.js');
|
|
4
|
+
|
|
5
|
+
const PING_SYM = Symbol('ping');
|
|
6
|
+
const PING_RESULT = {
|
|
7
|
+
value: PING_SYM,
|
|
8
|
+
done: false
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Derives a new {@link AsyncGenerator} based of {@link iterable}, that yields {@link PING_SYM}
|
|
12
|
+
* whenever no value has been yielded for {@link pingIntervalMs}.
|
|
13
|
+
*/ async function* withPing(iterable, pingIntervalMs) {
|
|
14
|
+
const timer = promiseTimer.createPromiseTimer(pingIntervalMs);
|
|
15
|
+
const iterator = iterable[Symbol.asyncIterator]();
|
|
16
|
+
while(true){
|
|
17
|
+
const nextPromise = iterator.next();
|
|
18
|
+
const pingPromise = timer.start().promise.then(()=>PING_RESULT);
|
|
19
|
+
let result;
|
|
20
|
+
try {
|
|
21
|
+
result = await Promise.race([
|
|
22
|
+
nextPromise,
|
|
23
|
+
pingPromise
|
|
24
|
+
]);
|
|
25
|
+
} finally{
|
|
26
|
+
timer.clear();
|
|
27
|
+
}
|
|
28
|
+
if (result.done) {
|
|
29
|
+
return result.value;
|
|
30
|
+
}
|
|
31
|
+
yield result.value;
|
|
32
|
+
timer.reset();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.PING_SYM = PING_SYM;
|
|
37
|
+
exports.withPing = withPing;
|