1616 */
1717import express from 'express' ;
1818import { Worker } from 'node:worker_threads' ;
19- import { JsTsAnalysisOutputWithAst } from '../../jsts/src/analysis/analysis.js' ;
2019import { handleRequest } from './handle-request.js' ;
21- import { AnalysisOutput } from '../../shared/src/types/analysis.js' ;
22- import { RequestResult , RequestType } from './request.js' ;
20+ import { RequestResult , RequestType , WsIncrementalResult } from './request.js' ;
2321import { WorkerData } from '../../shared/src/helpers/worker.js' ;
22+ import { info , debug , error } from '../../shared/src/helpers/logging.js' ;
23+ import type { RawData , WebSocket } from 'ws' ;
24+ import { WorkerMessageListeners } from './router.js' ;
2425
2526/**
2627 * Returns a delegate function to handle an HTTP request
2728 */
28- export function createDelegator ( worker : Worker | undefined , workerData : WorkerData ) {
29- return function ( type : RequestType ) {
30- return worker ? createWorkerHandler ( worker , type ) : createHandler ( type , workerData ) ;
31- } ;
29+ export function createDelegator (
30+ worker : Worker | undefined ,
31+ workerData : WorkerData ,
32+ listeners : WorkerMessageListeners ,
33+ ) {
34+ return worker
35+ ? ( type : RequestType ) => createWorkerHandler ( worker , type , listeners )
36+ : ( type : RequestType ) => createHandler ( type , workerData ) ;
3237}
3338
3439/**
@@ -46,14 +51,16 @@ function createHandler(type: RequestType, workerData: WorkerData) {
4651 } ;
4752}
4853
49- function createWorkerHandler ( worker : Worker , type : RequestType ) {
54+ function createWorkerHandler ( worker : Worker , type : RequestType , listeners : WorkerMessageListeners ) {
5055 return async (
5156 request : express . Request ,
5257 response : express . Response ,
5358 next : express . NextFunction ,
5459 ) => {
55- worker . once ( 'message' , message => {
56- handleResult ( message , response , next ) ;
60+ listeners . oneTimers . push ( message => {
61+ if ( ! message . ws ) {
62+ handleResult ( message , response , next ) ;
63+ }
5764 } ) ;
5865 worker . postMessage ( { type, data : request . body } ) ;
5966 } ;
@@ -75,6 +82,53 @@ function handleResult(
7582 }
7683}
7784
78- export function outputContainsAst ( result : AnalysisOutput ) : result is JsTsAnalysisOutputWithAst {
79- return 'astFilePath' in result ;
85+ /**
86+ * Returns a delegate function to handle a web socket message
87+ */
88+ export function createWsDelegator (
89+ worker : Worker | undefined ,
90+ workerData : WorkerData ,
91+ listeners : WorkerMessageListeners ,
92+ ) {
93+ return ( ws : WebSocket ) => {
94+ info ( 'WebSocket client connected on /ws' ) ;
95+ if ( worker ) {
96+ listeners . permanent . push ( message => {
97+ if ( message . ws ) {
98+ handleWsResult ( ws , message . results ) ;
99+ }
100+ } ) ;
101+ }
102+
103+ ws . on ( 'message' , async message => {
104+ const data = { type : 'on-analyze-project' as const , data : decodeMessage ( message ) , ws : true } ;
105+ if ( worker ) {
106+ worker . postMessage ( data ) ;
107+ } else {
108+ await handleRequest ( data , workerData , message => handleWsResult ( ws , message ) ) ;
109+ }
110+ } ) ;
111+
112+ ws . on ( 'close' , ( code , reason ) => {
113+ debug ( `WebSocket client disconnected: ${ reason } with code ${ code } ` ) ;
114+ } ) ;
115+
116+ ws . on ( 'error' , err => {
117+ error ( `WebSocket client error: ${ err } ` ) ;
118+ } ) ;
119+ } ;
120+ }
121+
122+ function handleWsResult ( ws : WebSocket , message : WsIncrementalResult ) {
123+ ws . send ( JSON . stringify ( message ) ) ;
124+ }
125+
126+ function decodeMessage ( message : RawData ) {
127+ let jsonString = '' ;
128+ if ( Buffer . isBuffer ( message ) ) {
129+ jsonString = message . toString ( 'utf8' ) ;
130+ } else if ( Array . isArray ( message ) ) {
131+ jsonString = Buffer . concat ( message ) . toString ( 'utf8' ) ;
132+ }
133+ return JSON . parse ( jsonString ) ;
80134}
0 commit comments