@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.
Files changed (34) hide show
  1. package/dist/bundle-analysis.json +129 -80
  2. package/dist/unstable-core-do-not-import/stream/sse.d.ts +3 -3
  3. package/dist/unstable-core-do-not-import/stream/sse.d.ts.map +1 -1
  4. package/dist/unstable-core-do-not-import/stream/sse.js +53 -65
  5. package/dist/unstable-core-do-not-import/stream/sse.mjs +55 -67
  6. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts +17 -0
  7. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.d.ts.map +1 -0
  8. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.js +59 -0
  9. package/dist/unstable-core-do-not-import/stream/utils/asyncIterable.mjs +56 -0
  10. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts +0 -11
  11. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.d.ts.map +1 -1
  12. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.js +0 -29
  13. package/dist/unstable-core-do-not-import/stream/utils/createDeferred.mjs +1 -29
  14. package/dist/unstable-core-do-not-import/stream/utils/promiseTimer.d.ts +8 -0
  15. package/dist/unstable-core-do-not-import/stream/utils/promiseTimer.d.ts.map +1 -0
  16. package/dist/unstable-core-do-not-import/stream/utils/promiseTimer.js +38 -0
  17. package/dist/unstable-core-do-not-import/stream/utils/promiseTimer.mjs +36 -0
  18. package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts +7 -0
  19. package/dist/unstable-core-do-not-import/stream/utils/withPing.d.ts.map +1 -0
  20. package/dist/unstable-core-do-not-import/stream/utils/withPing.js +37 -0
  21. package/dist/unstable-core-do-not-import/stream/utils/withPing.mjs +34 -0
  22. package/dist/unstable-core-do-not-import/utils.d.ts +2 -0
  23. package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
  24. package/dist/unstable-core-do-not-import/utils.js +7 -0
  25. package/dist/unstable-core-do-not-import/utils.mjs +6 -1
  26. package/dist/unstable-core-do-not-import.js +2 -1
  27. package/dist/unstable-core-do-not-import.mjs +2 -2
  28. package/package.json +3 -3
  29. package/src/unstable-core-do-not-import/stream/sse.ts +60 -91
  30. package/src/unstable-core-do-not-import/stream/utils/asyncIterable.ts +62 -0
  31. package/src/unstable-core-do-not-import/stream/utils/createDeferred.ts +0 -36
  32. package/src/unstable-core-do-not-import/stream/utils/promiseTimer.ts +40 -0
  33. package/src/unstable-core-do-not-import/stream/utils/withPing.ts +35 -0
  34. 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 =(v)=>v } = opts;
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
- const iterator = opts.data[Symbol.asyncIterator]();
25
- const closedPromise = stream.cancelledPromise.then(()=>'closed');
26
- const maxDurationPromise = createDeferred.createTimeoutPromise(opts.maxDurationMs ?? Infinity, 'maxDuration');
27
- let nextPromise = iterator.next();
28
- while(true){
29
- const pingPromise = createDeferred.createTimeoutPromise(ping.enabled ? ping.intervalMs : Infinity, 'ping');
30
- const next = await Promise.race([
31
- nextPromise.catch((err)=>{
32
- if (err instanceof Error && err.name === 'AbortError') {
33
- // Ensures that aborting the request doesn't throw an error
34
- return 'aborted';
35
- }
36
- return TRPCError.getTRPCErrorFromUnknown(err);
37
- }),
38
- pingPromise.promise,
39
- closedPromise,
40
- maxDurationPromise.promise
41
- ]);
42
- pingPromise.clear();
43
- if (next === 'aborted') {
44
- break;
45
- }
46
- if (next === 'closed') {
47
- break;
48
- }
49
- if (next === 'maxDuration') {
50
- break;
51
- }
52
- if (next === 'ping') {
53
- stream.controller.enqueue({
54
- comment: 'ping'
55
- });
56
- continue;
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
- if (next instanceof Error) {
59
- const data = opts.formatError ? opts.formatError({
60
- error: next
61
- }) : null;
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
- if (next.done) {
69
- break;
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
- } catch {}
93
- }).catch((error)=>{
94
- return stream.controller.error(error);
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 { createTimeoutPromise, createDeferred } from './utils/createDeferred.mjs';
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 =(v)=>v } = opts;
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
- const iterator = opts.data[Symbol.asyncIterator]();
23
- const closedPromise = stream.cancelledPromise.then(()=>'closed');
24
- const maxDurationPromise = createTimeoutPromise(opts.maxDurationMs ?? Infinity, 'maxDuration');
25
- let nextPromise = iterator.next();
26
- while(true){
27
- const pingPromise = createTimeoutPromise(ping.enabled ? ping.intervalMs : Infinity, 'ping');
28
- const next = await Promise.race([
29
- nextPromise.catch((err)=>{
30
- if (err instanceof Error && err.name === 'AbortError') {
31
- // Ensures that aborting the request doesn't throw an error
32
- return 'aborted';
33
- }
34
- return getTRPCErrorFromUnknown(err);
35
- }),
36
- pingPromise.promise,
37
- closedPromise,
38
- maxDurationPromise.promise
39
- ]);
40
- pingPromise.clear();
41
- if (next === 'aborted') {
42
- break;
43
- }
44
- if (next === 'closed') {
45
- break;
46
- }
47
- if (next === 'maxDuration') {
48
- break;
49
- }
50
- if (next === 'ping') {
51
- stream.controller.enqueue({
52
- comment: 'ping'
53
- });
54
- continue;
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
- if (next instanceof Error) {
57
- const data = opts.formatError ? opts.formatError({
58
- error: next
59
- }) : null;
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
- if (next.done) {
67
- break;
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
- } catch {}
91
- }).catch((error)=>{
92
- return stream.controller.error(error);
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;AAEzE,eAAO,MAAM,oBAAoB,GAAI,MAAM,aAC9B,MAAM,SACV,MAAM;;IAuBX;;OAEG;;IAEH;;OAEG;;CAGN,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, createTimeoutPromise };
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;