mirror of
https://github.com/janishutz/fundamentals-of-webengineering.git
synced 2025-11-25 05:44:24 +00:00
[Task 3] SSE
This commit is contained in:
21
task_3_react/src/client/sse.ts
Normal file
21
task_3_react/src/client/sse.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
interface SSEMessage {
|
||||
'event': string,
|
||||
'data': string
|
||||
}
|
||||
const eventSource: EventSource = new EventSource( '/sse' );
|
||||
|
||||
eventSource.onopen = () => {
|
||||
document.dispatchEvent( new CustomEvent( 'sse:connect', {
|
||||
'detail': 'success',
|
||||
'cancelable': false
|
||||
} ) );
|
||||
};
|
||||
|
||||
eventSource.onmessage = event => {
|
||||
const data: SSEMessage = JSON.parse( event.data );
|
||||
|
||||
document.dispatchEvent( new CustomEvent( 'sse:' + data.event, {
|
||||
'cancelable': false,
|
||||
'detail': data.data
|
||||
} ) );
|
||||
};
|
||||
@@ -1,4 +1,7 @@
|
||||
import * as fs from 'node:fs/promises';
|
||||
import {
|
||||
EventEmitter
|
||||
} from 'node:stream';
|
||||
import ViteExpress from 'vite-express';
|
||||
import express from 'express';
|
||||
import multer from 'multer';
|
||||
@@ -17,6 +20,8 @@ const storage = multer.diskStorage( {
|
||||
// Suggested in Multer's readme
|
||||
const uniqueSuffix = Date.now() + '-' + Math.round( Math.random() * 1E3 );
|
||||
|
||||
fileEvent.emit( 'uploaded', file.fieldname + '-' + uniqueSuffix );
|
||||
|
||||
cb( null, file.fieldname + '-' + uniqueSuffix );
|
||||
}
|
||||
} );
|
||||
@@ -25,6 +30,10 @@ const upload = multer( {
|
||||
'storage': storage
|
||||
} );
|
||||
|
||||
class FileEvent extends EventEmitter {}
|
||||
|
||||
const fileEvent = new FileEvent();
|
||||
|
||||
app.post(
|
||||
'/upload',
|
||||
upload.single( 'dataFile' ),
|
||||
@@ -78,8 +87,9 @@ app.delete( '/delete/:fileName', async ( req, res ) => {
|
||||
);
|
||||
|
||||
try {
|
||||
await fs.unlink( filePath ); // deletes the file
|
||||
await fs.rm( filePath ); // deletes the file
|
||||
res.status( 200 ).send( 'File deleted successfully' );
|
||||
fileEvent.emit( 'deleted', filePath );
|
||||
} catch ( error ) {
|
||||
console.error( 'Error deleting file:', error );
|
||||
res.status( 500 ).send( 'Error deleting file' );
|
||||
@@ -93,6 +103,57 @@ app.get( '/hello', async function ( _req, res ) {
|
||||
} );
|
||||
} );
|
||||
|
||||
|
||||
interface SSESubscriber {
|
||||
'uuid': string;
|
||||
'response': express.Response;
|
||||
}
|
||||
|
||||
interface SSESubscribers {
|
||||
[id: string]: SSESubscriber | undefined;
|
||||
}
|
||||
const subscribers: SSESubscribers = {};
|
||||
|
||||
app.get( '/sse', async ( request: express.Request, response: express.Response ) => {
|
||||
response.writeHead( 200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Connection': 'keep-alive',
|
||||
} );
|
||||
response.status( 200 );
|
||||
response.flushHeaders();
|
||||
response.write( `data: ${ JSON.stringify( [] ) }\n\n` );
|
||||
|
||||
const uuid = crypto.randomUUID();
|
||||
|
||||
subscribers[uuid] = {
|
||||
'uuid': uuid,
|
||||
'response': response
|
||||
};
|
||||
|
||||
request.on( 'close', () => {
|
||||
subscribers[ uuid ] = undefined;
|
||||
} );
|
||||
} );
|
||||
|
||||
const sendSSEData = ( event: string, data: string ) => {
|
||||
const subs = Object.values( subscribers );
|
||||
|
||||
for ( let i = 0; i < subs.length; i++ ) {
|
||||
subs[i]!.response.write( `data: ${ JSON.stringify( {
|
||||
'event': event,
|
||||
'data': data
|
||||
} ) }` );
|
||||
}
|
||||
};
|
||||
|
||||
fileEvent.on( 'uploaded', file => {
|
||||
sendSSEData( 'uploaded', file );
|
||||
} );
|
||||
fileEvent.on( 'deleted', file => {
|
||||
sendSSEData( 'deleted', file );
|
||||
} );
|
||||
|
||||
// Do not change below this line
|
||||
ViteExpress.listen(
|
||||
app, 5173, () => console.log( 'Server is listening on http://localhost:5173' ),
|
||||
|
||||
Reference in New Issue
Block a user