( res: ServerResponse, waitUntilForEnd?: Promise<unknown> )
| 14 | } |
| 15 | |
| 16 | function createWriterFromResponse( |
| 17 | res: ServerResponse, |
| 18 | waitUntilForEnd?: Promise<unknown> |
| 19 | ): WritableStream<Uint8Array> { |
| 20 | let started = false |
| 21 | |
| 22 | // Create a promise that will resolve once the response has drained. See |
| 23 | // https://nodejs.org/api/stream.html#stream_event_drain |
| 24 | let drained = new DetachedPromise<void>() |
| 25 | function onDrain() { |
| 26 | drained.resolve() |
| 27 | } |
| 28 | res.on('drain', onDrain) |
| 29 | |
| 30 | // If the finish event fires, it means we shouldn't block and wait for the |
| 31 | // drain event. |
| 32 | res.once('close', () => { |
| 33 | res.off('drain', onDrain) |
| 34 | drained.resolve() |
| 35 | }) |
| 36 | |
| 37 | // Create a promise that will resolve once the response has finished. See |
| 38 | // https://nodejs.org/api/http.html#event-finish_1 |
| 39 | const finished = new DetachedPromise<void>() |
| 40 | res.once('finish', () => { |
| 41 | finished.resolve() |
| 42 | }) |
| 43 | |
| 44 | // Create a writable stream that will write to the response. |
| 45 | return new WritableStream<Uint8Array>({ |
| 46 | write: async (chunk) => { |
| 47 | // You'd think we'd want to use `start` instead of placing this in `write` |
| 48 | // but this ensures that we don't actually flush the headers until we've |
| 49 | // started writing chunks. |
| 50 | if (!started) { |
| 51 | started = true |
| 52 | |
| 53 | if ( |
| 54 | 'performance' in globalThis && |
| 55 | process.env.NEXT_OTEL_PERFORMANCE_PREFIX |
| 56 | ) { |
| 57 | const metrics = getClientComponentLoaderMetrics() |
| 58 | if (metrics) { |
| 59 | performance.measure( |
| 60 | `${process.env.NEXT_OTEL_PERFORMANCE_PREFIX}:next-client-component-loading`, |
| 61 | { |
| 62 | start: metrics.clientComponentLoadStart, |
| 63 | end: |
| 64 | metrics.clientComponentLoadStart + |
| 65 | metrics.clientComponentLoadTimes, |
| 66 | } |
| 67 | ) |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | res.flushHeaders() |
| 72 | getTracer().trace( |
| 73 | NextNodeServerSpan.startResponse, |
no test coverage detected