Skip to content

Commit 1d3b6c0

Browse files
committed
update invitations in real-time
1 parent e844f0a commit 1d3b6c0

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

apps/events/src/routes/playground.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ const App = ({
270270
}
271271
const message: EventMessage = { type: 'event', event: spaceEvent.value, spaceId: invitation.spaceId };
272272
websocketConnection?.send(JSON.stringify(message));
273+
274+
// temporary until we have define a strategy for accepting invitations response
275+
setTimeout(() => {
276+
const message2: RequestListInvitations = { type: 'list-invitations' };
277+
websocketConnection?.send(JSON.stringify(message2));
278+
}, 1000);
273279
}}
274280
/>
275281
<h2 className="text-lg">Spaces</h2>

apps/server/src/index.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
import cors from 'cors';
22
import 'dotenv/config';
3-
import { parse } from 'node:url';
43
import { Effect, Exit, Schema } from 'effect';
54
import express from 'express';
65
import type { ResponseListInvitations, ResponseListSpaces, ResponseSpace } from 'graph-framework-messages';
76
import { RequestMessage } from 'graph-framework-messages';
87
import { applyEvent } from 'graph-framework-space-events';
9-
import type WebSocket from 'ws';
10-
import { WebSocketServer } from 'ws';
8+
import { parse } from 'node:url';
9+
import WebSocket, { WebSocketServer } from 'ws';
1110
import { applySpaceEvent } from './handlers/applySpaceEvent.js';
1211
import { createSpace } from './handlers/createSpace.js';
1312
import { getSpace } from './handlers/getSpace.js';
1413
import { listInvitations } from './handlers/listInvitations.js';
1514
import { listSpaces } from './handlers/listSpaces.js';
1615
import { tmpInitAccount } from './handlers/tmpInitAccount.js';
1716
import { assertExhaustive } from './utils/assertExhaustive.js';
17+
interface CustomWebSocket extends WebSocket {
18+
accountId: string;
19+
subscribedSpaces: Set<string>;
20+
}
1821

1922
const decodeRequestMessage = Schema.decodeUnknownEither(RequestMessage);
2023

@@ -38,13 +41,15 @@ const server = app.listen(PORT, () => {
3841
console.log(`Listening on port ${PORT}`);
3942
});
4043

41-
webSocketServer.on('connection', async (webSocket: WebSocket, request: Request) => {
44+
webSocketServer.on('connection', async (webSocket: CustomWebSocket, request: Request) => {
4245
const params = parse(request.url, true);
4346
if (!params.query.accountId || typeof params.query.accountId !== 'string') {
4447
webSocket.close();
4548
return;
4649
}
4750
const accountId = params.query.accountId;
51+
webSocket.accountId = accountId;
52+
webSocket.subscribedSpaces = new Set();
4853

4954
console.log('Connection established', accountId);
5055
webSocket.on('message', async (message) => {
@@ -101,6 +106,18 @@ webSocketServer.on('connection', async (webSocket: WebSocket, request: Request)
101106
type: 'space',
102107
};
103108
webSocket.send(JSON.stringify(outgoingMessage));
109+
for (const client of webSocketServer.clients as Set<CustomWebSocket>) {
110+
if (
111+
client.readyState === WebSocket.OPEN &&
112+
client.accountId === data.event.transaction.signaturePublicKey
113+
) {
114+
const invitations = await listInvitations({ accountId: client.accountId });
115+
const outgoingMessage: ResponseListInvitations = { type: 'list-invitations', invitations: invitations };
116+
// for now sending the entire list of invitations to the client - we could send only a single one
117+
client.send(JSON.stringify(outgoingMessage));
118+
}
119+
}
120+
104121
break;
105122
}
106123
case 'event': {

0 commit comments

Comments
 (0)