@fails-components/webtransport 0.2.2 → 0.3.0
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/CMakeLists.txt +3 -0
- package/dist/lib/client.d.ts +7 -3
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/dom.d.ts +15 -4
- package/dist/lib/dom.d.ts.map +1 -1
- package/dist/lib/error.d.ts +8 -0
- package/dist/lib/error.d.ts.map +1 -0
- package/dist/lib/event-loop.d.ts +4 -2
- package/dist/lib/event-loop.d.ts.map +1 -1
- package/dist/lib/native.d.ts.map +1 -1
- package/dist/lib/server.d.ts +5 -2
- package/dist/lib/server.d.ts.map +1 -1
- package/dist/lib/session.d.ts +36 -23
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/stream.d.ts +15 -4
- package/dist/lib/stream.d.ts.map +1 -1
- package/dist/lib/transport.d.ts +12 -3
- package/dist/lib/transport.d.ts.map +1 -1
- package/dist/lib/types.d.ts +43 -4
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/webtransport.d.ts +11 -21
- package/dist/lib/webtransport.d.ts.map +1 -1
- package/dist/test/datagrams.spec.d.ts.map +1 -1
- package/dist/test/event-loop.node.d.ts +2 -0
- package/dist/test/event-loop.node.d.ts.map +1 -0
- package/dist/test/fixtures/chai.d.ts.map +1 -1
- package/dist/test/fixtures/known-bytes.d.ts +6 -0
- package/dist/test/fixtures/known-bytes.d.ts.map +1 -0
- package/dist/test/fixtures/read-cert-hash.d.ts +6 -0
- package/dist/test/fixtures/read-cert-hash.d.ts.map +1 -0
- package/dist/test/fixtures/read-stream.d.ts +10 -1
- package/dist/test/fixtures/read-stream.d.ts.map +1 -1
- package/dist/test/fixtures/reader-value.d.ts +16 -1
- package/dist/test/fixtures/reader-value.d.ts.map +1 -1
- package/dist/test/fixtures/server.d.ts +0 -5
- package/dist/test/fixtures/server.d.ts.map +1 -1
- package/dist/test/fixtures/webtransport.browser.d.ts +3 -0
- package/dist/test/fixtures/webtransport.browser.d.ts.map +1 -0
- package/dist/test/fixtures/webtransport.d.ts +3 -0
- package/dist/test/fixtures/webtransport.d.ts.map +1 -0
- package/dist/test/fixtures/write-stream.d.ts.map +1 -1
- package/dist/test/index.d.ts +2 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/session.spec.d.ts +5 -0
- package/dist/test/session.spec.d.ts.map +1 -0
- package/dist/test/unidirectional-streams.spec.d.ts +1 -4
- package/dist/test/unidirectional-streams.spec.d.ts.map +1 -1
- package/lib/client.js +57 -43
- package/lib/dom.ts +18 -4
- package/lib/error.js +10 -0
- package/lib/event-loop.js +8 -5
- package/lib/native.js +4 -1
- package/lib/server.js +18 -10
- package/lib/session.js +145 -32
- package/lib/stream.js +51 -22
- package/lib/transport.js +48 -10
- package/lib/types.ts +53 -5
- package/lib/utils.js +13 -0
- package/lib/webtransport.js +10 -18
- package/{test → old_test}/echoserver.js +1 -2
- package/{test → old_test}/test.js +5 -3
- package/package.json +16 -5
- package/readme.md +64 -0
- package/src/http3client.cc +2 -2
- package/src/http3dispatcher.cc +3 -2
- package/src/http3dispatcher.h +2 -1
- package/src/http3eventloop.cc +106 -2
- package/src/http3eventloop.h +13 -0
- package/src/http3wtsessionvisitor.cc +2 -0
- package/src/http3wtsessionvisitor.h +41 -1
- package/test/bidirectional-streams.spec.js +41 -97
- package/test/datagrams.spec.js +50 -99
- package/test/fixtures/chai.js +2 -0
- package/test/fixtures/known-bytes.js +15 -0
- package/test/fixtures/read-cert-hash.js +7 -0
- package/test/fixtures/read-stream.js +5 -0
- package/test/fixtures/reader-value.js +32 -0
- package/test/fixtures/server.js +237 -21
- package/test/fixtures/webtransport.browser.js +2 -0
- package/test/fixtures/webtransport.js +3 -0
- package/test/fixtures/write-stream.js +8 -1
- package/test/index.js +87 -0
- package/test/session.spec.js +159 -0
- package/test/unidirectional-streams.spec.js +67 -138
- package/tsconfig.json +0 -1
- package/dist/test/echoclient.d.ts +0 -2
- package/dist/test/echoclient.d.ts.map +0 -1
- package/dist/test/echoserver.d.ts +0 -2
- package/dist/test/echoserver.d.ts.map +0 -1
- package/dist/test/event-loop.spec.d.ts +0 -2
- package/dist/test/event-loop.spec.d.ts.map +0 -1
- package/dist/test/test.d.ts +0 -2
- package/dist/test/test.d.ts.map +0 -1
- package/dist/test/testsuite.d.ts +0 -25
- package/dist/test/testsuite.d.ts.map +0 -1
- package/platform/base/strings/utf_ostream_operators.h +0 -5
- /package/{test → old_test}/echoclient.js +0 -0
- /package/{test → old_test}/testsuite.js +0 -0
- /package/test/{event-loop.spec.js → event-loop.node.js} +0 -0
|
@@ -1,136 +1,79 @@
|
|
|
1
1
|
/* eslint-env mocha */
|
|
2
2
|
|
|
3
|
-
import { createServer } from './fixtures/server.js'
|
|
4
3
|
import { getReaderValue } from './fixtures/reader-value.js'
|
|
5
|
-
import { WebTransport } from '../lib/index.js'
|
|
6
4
|
import { expect } from './fixtures/chai.js'
|
|
7
5
|
import { readStream } from './fixtures/read-stream.js'
|
|
8
6
|
import { writeStream } from './fixtures/write-stream.js'
|
|
9
|
-
import {
|
|
7
|
+
import { readCertHash } from './fixtures/read-cert-hash.js'
|
|
8
|
+
import WebTransport from './fixtures/webtransport.js'
|
|
10
9
|
import * as ui8 from 'uint8arrays'
|
|
10
|
+
import { KNOWN_BYTES, KNOWN_BYTES_LENGTH } from './fixtures/known-bytes.js'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @template T
|
|
14
14
|
* @typedef {import('../lib/types').Deferred<T>} Deferred<T>
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
const SERVER_PATH = '/bidirectional-streams'
|
|
18
|
-
|
|
19
17
|
describe('bidirectional streams', function () {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
// FIXME: sometimes there are seemingly arbitrary 5s delays in
|
|
19
|
+
// communicating with the server under node.js
|
|
20
|
+
this.timeout(30000)
|
|
21
|
+
|
|
24
22
|
/** @type {import('../lib/dom').WebTransport | undefined} */
|
|
25
23
|
let client
|
|
26
|
-
/** @type {string} */
|
|
27
|
-
let url
|
|
28
|
-
|
|
29
|
-
this.timeout(30000) // this can vary depending on the setup and is not an error
|
|
30
|
-
// but it smells like a work around regarding a deeper problem
|
|
31
|
-
|
|
32
|
-
beforeEach(async () => {
|
|
33
|
-
this.timeout(2000)
|
|
34
|
-
;({ server, certificate } = await createServer())
|
|
35
|
-
server.startServer()
|
|
36
|
-
await server.ready
|
|
37
|
-
|
|
38
|
-
const address = server.address()
|
|
39
|
-
|
|
40
|
-
if (address == null || address.port == null) {
|
|
41
|
-
throw new Error('No address')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
url = `https://${address.host}:${address.port}`
|
|
45
|
-
})
|
|
46
24
|
|
|
47
25
|
// @ts-ignore
|
|
48
26
|
afterEach(async () => {
|
|
49
27
|
if (client != null) {
|
|
50
28
|
client.close()
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (server != null) {
|
|
54
|
-
server.stopServer()
|
|
55
|
-
await server.closed
|
|
29
|
+
client = undefined
|
|
56
30
|
}
|
|
57
31
|
})
|
|
58
32
|
|
|
59
33
|
it('sends and receives data over an outgoing bidirectional stream', async () => {
|
|
60
|
-
this.timeout(200)
|
|
61
|
-
// server context - waits for the client to open a bidi stream and pipes it back to them
|
|
62
|
-
Promise.resolve().then(async () => {
|
|
63
|
-
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
64
|
-
if (!session) throw new Error('Got no session')
|
|
65
|
-
const bidiStream = await getReaderValue(
|
|
66
|
-
session.incomingBidirectionalStreams
|
|
67
|
-
)
|
|
68
|
-
// redirect input to output
|
|
69
|
-
await bidiStream.readable.pipeTo(bidiStream.writable)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
34
|
// client context - connects to the server, opens a bidi stream, sends some data and reads the response
|
|
73
|
-
client = new WebTransport(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
35
|
+
client = new WebTransport(
|
|
36
|
+
`${process.env.SERVER_URL}/bidirectional_client_initiated_echo`,
|
|
37
|
+
{
|
|
38
|
+
serverCertificateHashes: [
|
|
39
|
+
{
|
|
40
|
+
algorithm: 'sha-256',
|
|
41
|
+
value: readCertHash(process.env.CERT_HASH)
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
)
|
|
81
46
|
await client.ready
|
|
82
47
|
|
|
83
|
-
const input = [
|
|
84
|
-
Uint8Array.from([0, 1, 2, 3, 4]),
|
|
85
|
-
Uint8Array.from([5, 6, 7, 8, 9]),
|
|
86
|
-
Uint8Array.from([10, 11, 12, 13, 14])
|
|
87
|
-
]
|
|
88
|
-
|
|
89
48
|
const stream = await client.createBidirectionalStream()
|
|
90
|
-
await writeStream(stream.writable,
|
|
49
|
+
await writeStream(stream.writable, KNOWN_BYTES)
|
|
91
50
|
|
|
92
|
-
const output = await readStream(stream.readable,
|
|
93
|
-
expect(ui8.concat(
|
|
94
|
-
ui8.concat(
|
|
51
|
+
const output = await readStream(stream.readable, KNOWN_BYTES_LENGTH)
|
|
52
|
+
expect(ui8.concat(KNOWN_BYTES)).to.deep.equal(
|
|
53
|
+
ui8.concat(output),
|
|
95
54
|
'Did not receive the same bytes we sent'
|
|
96
55
|
)
|
|
97
56
|
})
|
|
98
57
|
|
|
99
58
|
it('sends and receives data over an incoming bidirectional stream', async () => {
|
|
100
|
-
this.timeout(200)
|
|
101
59
|
/** @type {Deferred<Uint8Array[]>} */
|
|
102
|
-
const serverData = defer()
|
|
103
|
-
const input = [
|
|
104
|
-
Uint8Array.from([0, 1, 2, 3, 4]),
|
|
105
|
-
Uint8Array.from([5, 6, 7, 8, 9]),
|
|
106
|
-
Uint8Array.from([10, 11, 12, 13, 14])
|
|
107
|
-
]
|
|
108
|
-
|
|
109
|
-
// server context - waits for the client to connect, opens a bidi stream, sends some data and reads the response
|
|
110
|
-
Promise.resolve().then(async () => {
|
|
111
|
-
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
112
|
-
if (!session) throw new Error('Got no session')
|
|
113
|
-
const stream = await session.createBidirectionalStream()
|
|
114
|
-
|
|
115
|
-
await writeStream(stream.writable, input)
|
|
116
|
-
|
|
117
|
-
const output = await readStream(stream.readable, ui8.concat(input).length)
|
|
118
|
-
serverData.resolve(output)
|
|
119
|
-
await stream.readable.cancel() // cancel so that the client can progress
|
|
120
|
-
})
|
|
121
60
|
|
|
122
61
|
// client context - waits for the server to open a bidi stream then pipes it back to them
|
|
123
|
-
client = new WebTransport(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
62
|
+
client = new WebTransport(
|
|
63
|
+
`${process.env.SERVER_URL}/bidirectional_server_initiated_echo`,
|
|
64
|
+
{
|
|
65
|
+
serverCertificateHashes: [
|
|
66
|
+
{
|
|
67
|
+
algorithm: 'sha-256',
|
|
68
|
+
value: readCertHash(process.env.CERT_HASH)
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
)
|
|
131
73
|
await client.ready
|
|
132
74
|
|
|
133
75
|
const bidiStream = await getReaderValue(client.incomingBidirectionalStreams)
|
|
76
|
+
|
|
134
77
|
// redirect input to output
|
|
135
78
|
try {
|
|
136
79
|
await bidiStream.readable.pipeTo(bidiStream.writable)
|
|
@@ -138,10 +81,11 @@ describe('bidirectional streams', function () {
|
|
|
138
81
|
console.log('Pipe to error (ignore)', error) // Actually all you can get is, that the fin is catched
|
|
139
82
|
}
|
|
140
83
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
)
|
|
84
|
+
// the remote will close the session
|
|
85
|
+
const result = await client.closed
|
|
86
|
+
|
|
87
|
+
// should receive the default close info
|
|
88
|
+
expect(result).to.have.property('reason', '')
|
|
89
|
+
expect(result).to.have.property('closeCode', 0)
|
|
146
90
|
})
|
|
147
91
|
})
|
package/test/datagrams.spec.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
/* eslint-env mocha */
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import { getReaderValue } from './fixtures/reader-value.js'
|
|
5
|
-
import { WebTransport } from '../lib/index.js'
|
|
3
|
+
import WebTransport from './fixtures/webtransport.js'
|
|
6
4
|
import { expect } from './fixtures/chai.js'
|
|
7
5
|
import { readStream } from './fixtures/read-stream.js'
|
|
8
|
-
import {
|
|
9
|
-
import * as ui8 from 'uint8arrays'
|
|
6
|
+
import { readCertHash } from './fixtures/read-cert-hash.js'
|
|
10
7
|
import { pTimeout } from './fixtures/p-timeout.js'
|
|
11
8
|
|
|
12
9
|
/**
|
|
@@ -14,119 +11,75 @@ import { pTimeout } from './fixtures/p-timeout.js'
|
|
|
14
11
|
* @typedef {import('../lib/types').Deferred<T>} Deferred<T>
|
|
15
12
|
*/
|
|
16
13
|
|
|
17
|
-
const SERVER_PATH = '/datagrams'
|
|
18
|
-
|
|
19
14
|
describe('datagrams', function () {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
// FIXME: sometimes there are seemingly arbitrary 5s delays in
|
|
16
|
+
// communicating with the server under node.js
|
|
17
|
+
this.timeout(30000)
|
|
18
|
+
|
|
24
19
|
/** @type {import('../lib/dom').WebTransport | undefined} */
|
|
25
20
|
let client
|
|
26
|
-
/** @type {string} */
|
|
27
|
-
let url
|
|
28
|
-
|
|
29
|
-
beforeEach(async () => {
|
|
30
|
-
;({ server, certificate } = await createServer())
|
|
31
|
-
server.startServer()
|
|
32
|
-
await server.ready
|
|
33
|
-
|
|
34
|
-
const address = server.address()
|
|
35
|
-
|
|
36
|
-
if (address == null || address.port == null) {
|
|
37
|
-
throw new Error('No address')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
url = `https://${address.host}:${address.port}`
|
|
41
|
-
})
|
|
42
21
|
|
|
43
22
|
// @ts-ignore
|
|
44
23
|
afterEach(async () => {
|
|
45
24
|
if (client != null) {
|
|
46
25
|
client.close()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (server != null) {
|
|
50
|
-
server.stopServer()
|
|
51
|
-
await server.closed
|
|
26
|
+
client = undefined
|
|
52
27
|
}
|
|
53
28
|
})
|
|
54
|
-
|
|
55
29
|
it('client sends datagrams to the server', async () => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
30
|
+
// client context - connects to the server, sends some datagrams and reads the response
|
|
31
|
+
client = new WebTransport(
|
|
32
|
+
`${process.env.SERVER_URL}/datagrams_client_send`,
|
|
33
|
+
{
|
|
34
|
+
serverCertificateHashes: [
|
|
35
|
+
{
|
|
36
|
+
algorithm: 'sha-256',
|
|
37
|
+
value: readCertHash(process.env.CERT_HASH)
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
await client.ready
|
|
60
43
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
})
|
|
44
|
+
const writer = client.datagrams.writable.getWriter()
|
|
45
|
+
let closed = false
|
|
64
46
|
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
47
|
+
// write datagrams until the server receives one and closes the connection
|
|
48
|
+
// eslint-disable-next-line promise/catch-or-return
|
|
49
|
+
Promise.resolve().then(async () => {
|
|
50
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
51
|
+
while (!closed) {
|
|
52
|
+
try {
|
|
53
|
+
await writer.ready
|
|
54
|
+
await writer.write(Uint8Array.from([0, 1, 2, 3, 4]))
|
|
55
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
56
|
+
} catch {
|
|
57
|
+
// the session can be closed while we are writing
|
|
71
58
|
}
|
|
72
|
-
|
|
59
|
+
}
|
|
73
60
|
})
|
|
74
|
-
await client.ready
|
|
75
|
-
|
|
76
|
-
const input = [
|
|
77
|
-
Uint8Array.from([0, 1, 2, 3, 4]),
|
|
78
|
-
Uint8Array.from([5, 6, 7, 8, 9]),
|
|
79
|
-
Uint8Array.from([10, 11, 12, 13, 14])
|
|
80
|
-
]
|
|
81
61
|
|
|
82
|
-
await
|
|
62
|
+
const result = await client.closed
|
|
63
|
+
closed = true
|
|
83
64
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
)
|
|
88
|
-
expect(output).to.deep.equal(
|
|
89
|
-
input,
|
|
90
|
-
'Did not receive the same bytes we sent'
|
|
91
|
-
)
|
|
65
|
+
// should receive the default close info
|
|
66
|
+
expect(result).to.have.property('reason', '')
|
|
67
|
+
expect(result).to.have.property('closeCode', 0)
|
|
92
68
|
})
|
|
93
69
|
|
|
94
70
|
it('receives datagrams from the server', async () => {
|
|
95
|
-
this.timeout(200)
|
|
96
|
-
|
|
97
|
-
// server context - waits for the client to connect, sends some datagrams and reads the response
|
|
98
|
-
Promise.resolve().then(async () => {
|
|
99
|
-
const session = await getReaderValue(server.sessionStream(SERVER_PATH))
|
|
100
|
-
|
|
101
|
-
let closed = false
|
|
102
|
-
const writer = session.datagrams.writable.getWriter()
|
|
103
|
-
Promise.resolve().then(async () => {
|
|
104
|
-
// eslint-disable-next-line no-unmodified-loop-condition
|
|
105
|
-
while (!closed) {
|
|
106
|
-
try {
|
|
107
|
-
await writer.ready
|
|
108
|
-
await writer.write(Uint8Array.from([0, 1, 2, 3, 4]))
|
|
109
|
-
await new Promise((resolve) => setTimeout(resolve, 1)) // do not flood everything
|
|
110
|
-
} catch {
|
|
111
|
-
// the session can be closed while we are writing
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
// have to close the session to end the client's datagram stream
|
|
117
|
-
await session.closed
|
|
118
|
-
closed = true
|
|
119
|
-
})
|
|
120
|
-
|
|
121
71
|
// client context - pipes the server's datagrams back to them
|
|
122
|
-
client = new WebTransport(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
72
|
+
client = new WebTransport(
|
|
73
|
+
`${process.env.SERVER_URL}/datagrams_server_send`,
|
|
74
|
+
{
|
|
75
|
+
serverCertificateHashes: [
|
|
76
|
+
{
|
|
77
|
+
algorithm: 'sha-256',
|
|
78
|
+
value: readCertHash(process.env.CERT_HASH)
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
)
|
|
130
83
|
await client.ready
|
|
131
84
|
|
|
132
85
|
// datagram transport is unreliable, at least one message should make it through
|
|
@@ -136,8 +89,6 @@ describe('datagrams', function () {
|
|
|
136
89
|
readStream(client.datagrams.readable, expected),
|
|
137
90
|
1000
|
|
138
91
|
)
|
|
139
|
-
await client.close()
|
|
140
|
-
client = undefined
|
|
141
92
|
expect(received).to.have.lengthOf(expected)
|
|
142
93
|
})
|
|
143
94
|
})
|
package/test/fixtures/chai.js
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bytes send by tests
|
|
3
|
+
*/
|
|
4
|
+
export const KNOWN_BYTES = [
|
|
5
|
+
Uint8Array.from([0, 1, 2, 3, 4]),
|
|
6
|
+
Uint8Array.from([5, 6, 7, 8, 9]),
|
|
7
|
+
Uint8Array.from([10, 11, 12, 13, 14]),
|
|
8
|
+
Uint8Array.from([15, 16, 17, 18, 19]),
|
|
9
|
+
Uint8Array.from([20, 21, 22, 23, 24])
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
export const KNOWN_BYTES_LENGTH = KNOWN_BYTES.reduce(
|
|
13
|
+
(accumulator, currentValue) => accumulator + currentValue.length,
|
|
14
|
+
0
|
|
15
|
+
)
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T
|
|
3
|
+
* @typedef {import('node:stream/web').ReadableStream<T>} ReadableStream<T>
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* @template T
|
|
3
8
|
* @param {ReadableStream<T>} readableStream
|
|
@@ -22,3 +27,30 @@ export async function getReaderValue(readableStream) {
|
|
|
22
27
|
reader.releaseLock()
|
|
23
28
|
}
|
|
24
29
|
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @template T
|
|
33
|
+
* @param {ReadableStream<T>} readableStream
|
|
34
|
+
* @returns {AsyncGenerator<T>}
|
|
35
|
+
*/
|
|
36
|
+
export async function* getReaderStream(readableStream) {
|
|
37
|
+
const reader = readableStream.getReader()
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
while (true) {
|
|
41
|
+
const { done, value } = await reader.read()
|
|
42
|
+
|
|
43
|
+
if (done) {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!value) {
|
|
48
|
+
throw new Error('Stream value was undefined')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
yield value
|
|
52
|
+
}
|
|
53
|
+
} finally {
|
|
54
|
+
reader.releaseLock()
|
|
55
|
+
}
|
|
56
|
+
}
|