@@ -50,7 +50,27 @@ const {readFile} = require('fs').promises;
5050
5151const React = require ( 'react' ) ;
5252
53- async function renderApp ( res , returnValue , formState , noCache ) {
53+ const activeDebugChannels =
54+ process . env . NODE_ENV === 'development' ? new Map ( ) : null ;
55+
56+ function getDebugChannel ( req ) {
57+ if ( process . env . NODE_ENV !== 'development' ) {
58+ return undefined ;
59+ }
60+ const requestId = req . get ( 'rsc-request-id' ) ;
61+ if ( ! requestId ) {
62+ return undefined ;
63+ }
64+ return activeDebugChannels . get ( requestId ) ;
65+ }
66+
67+ async function renderApp (
68+ res ,
69+ returnValue ,
70+ formState ,
71+ noCache ,
72+ promiseForDebugChannel
73+ ) {
5474 const { renderToPipeableStream} = await import (
5575 'react-server-dom-webpack/server'
5676 ) ;
@@ -101,7 +121,9 @@ async function renderApp(res, returnValue, formState, noCache) {
101121 ) ;
102122 // For client-invoked server actions we refresh the tree and return a return value.
103123 const payload = { root, returnValue, formState} ;
104- const { pipe} = renderToPipeableStream ( payload , moduleMap ) ;
124+ const { pipe} = renderToPipeableStream ( payload , moduleMap , {
125+ debugChannel : await promiseForDebugChannel ,
126+ } ) ;
105127 pipe ( res ) ;
106128}
107129
@@ -166,7 +188,7 @@ app.get('/', async function (req, res) {
166188 if ( 'prerender' in req . query ) {
167189 await prerenderApp ( res , null , null , noCache ) ;
168190 } else {
169- await renderApp ( res , null , null , noCache ) ;
191+ await renderApp ( res , null , null , noCache , getDebugChannel ( req ) ) ;
170192 }
171193} ) ;
172194
@@ -204,7 +226,7 @@ app.post('/', bodyParser.text(), async function (req, res) {
204226 // We handle the error on the client
205227 }
206228 // Refresh the client and return the value
207- renderApp ( res , result , null , noCache ) ;
229+ renderApp ( res , result , null , noCache , getDebugChannel ( req ) ) ;
208230 } else {
209231 // This is the progressive enhancement case
210232 const UndiciRequest = require ( 'undici' ) . Request ;
@@ -220,11 +242,11 @@ app.post('/', bodyParser.text(), async function (req, res) {
220242 // Wait for any mutations
221243 const result = await action ( ) ;
222244 const formState = decodeFormState ( result , formData ) ;
223- renderApp ( res , null , formState , noCache ) ;
245+ renderApp ( res , null , formState , noCache , undefined ) ;
224246 } catch ( x ) {
225247 const { setServerState} = await import ( '../src/ServerState.js' ) ;
226248 setServerState ( 'Error: ' + x . message ) ;
227- renderApp ( res , null , null , noCache ) ;
249+ renderApp ( res , null , null , noCache , undefined ) ;
228250 }
229251 }
230252} ) ;
@@ -324,7 +346,7 @@ if (process.env.NODE_ENV === 'development') {
324346 } ) ;
325347}
326348
327- app . listen ( 3001 , ( ) => {
349+ const httpServer = app . listen ( 3001 , ( ) => {
328350 console . log ( 'Regional Flight Server listening on port 3001...' ) ;
329351} ) ;
330352
@@ -346,3 +368,27 @@ app.on('error', function (error) {
346368 throw error ;
347369 }
348370} ) ;
371+
372+ if ( process . env . NODE_ENV === 'development' ) {
373+ // Open a websocket server for Debug information
374+ const WebSocket = require ( 'ws' ) ;
375+ const webSocketServer = new WebSocket . Server ( { noServer : true } ) ;
376+
377+ httpServer . on ( 'upgrade' , ( request , socket , head ) => {
378+ const DEBUG_CHANNEL_PATH = '/debug-channel?' ;
379+ if ( request . url . startsWith ( DEBUG_CHANNEL_PATH ) ) {
380+ const requestId = request . url . slice ( DEBUG_CHANNEL_PATH . length ) ;
381+ const promiseForWs = new Promise ( resolve => {
382+ webSocketServer . handleUpgrade ( request , socket , head , ws => {
383+ ws . on ( 'close' , ( ) => {
384+ activeDebugChannels . delete ( requestId ) ;
385+ } ) ;
386+ resolve ( ws ) ;
387+ } ) ;
388+ } ) ;
389+ activeDebugChannels . set ( requestId , promiseForWs ) ;
390+ } else {
391+ socket . destroy ( ) ;
392+ }
393+ } ) ;
394+ }
0 commit comments